knolleary / pubsubclient

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

MQTT Subscribe not working #163

Open hemalbavisi opened 8 years ago

hemalbavisi commented 8 years ago

I am very new to ESP8266 and MQTT. So Apologies if I haven't done it properly. I am using test.mosquitto.org server and trying to publish and subscribe the data. I am able to publish the data but subscribe part is not working. Nevertheless, I have tested subscribe part between two mobile and I am able to receive the data but I am not getting any data in the callback routine though I subscribed explicitly in the code. I have attached my code for your reference.

`

include

include

define wifi_ssid ""

define wifi_password ""

define mqtt_server "test.mosquitto.org"

define mqtt_user "test"

define mqtt_password "test"

define topic1 "SmartIOT/Temperature"

define topic2 "SmartIOT/Humidity"

define topic3 "SmartIOT/Switch"

void callback(char* topic, byte* payload, unsigned int length); WiFiClient espClient; PubSubClient client(mqtt_server, 1883, callback, espClient); void setup() { Serial.begin(115200); setup_wifi(); //client.setServer(mqtt_server, 1883); client.subscribe(topic3); }

// Callback function void callback(char* topic, byte* payload, unsigned int length) { // In order to republish this payload, a copy must be made // as the orignal payload buffer will be overwritten whilst // constructing the PUBLISH packet. Serial.println("Incoming data : "); Serial.println(topic); //Serial.println(payload); // Allocate the correct amount of memory for the payload copy byte* p = (byte*)malloc(length); // Copy the payload to the new buffer memcpy(p,payload,length); //client.publish("outTopic", p, length); // Free the memory free(p); }

void setup_wifi() { delay(10); // We start by connecting to a WiFi network Serial.println(); Serial.print("Connecting to "); Serial.println(wifi_ssid); WiFi.begin(wifi_ssid, wifi_password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP());

} void reconnect() { // Loop until we're reconnected while (!client.connected()) { Serial.print("Attempting MQTT connection..."); // Attempt to connect if (client.connect("TestMQTT")) { //* See //NOTE below Serial.println("connected");

    } else {
        Serial.print("failed, rc=");
        Serial.print(client.state());
        Serial.println(" try again in 5 seconds");
        // Wait 5 seconds before retrying
        delay(5000);
    }
}

} //NOTE: if a user/password is used for MQTT connection use: //if(client.connect("TestMQTT", mqtt_user, mqtt_password)) { void pubMQTT(String topic,float topic_val){ Serial.print("Newest topic " + topic + " value:"); Serial.println(String(topic_val).c_str()); client.publish(topic.c_str(), String(topic_val).c_str(), true); } //Variables used in loop() long lastMsg = 0; float t1 = 75.5; float t2 = 50.5; void loop() { if (!client.connected()) { reconnect(); client.subscribe(topic3); } client.loop(); //2 seconds minimum between Read Sensors and Publish long now = millis(); if (now - lastMsg > 2000) { lastMsg = now; //Read Sensors (simulate by increasing the values, range:0-90) t1 = t1>90 ? 0 : ++t1; t2 = t2>90 ? 0 : ++t2; //Publish Values to MQTT broker pubMQTT(topic1,t1); pubMQTT(topic2,t2); } } `

hemalbavisi commented 8 years ago

One more point -> Connection to server is frequently getting disconnected. However, I am able to see almost all the data from ESP2866 client to which my mobile application is subscribed to.

MartijnvdB commented 8 years ago

You did not specify that a callback should be executed when a message is received.

In setup(), after you do client.setServer(arg, arg), you specify which callback to execute, as follows:

client.setCallback(callbackName); // callback executed when message received

hemalbavisi commented 8 years ago

Thanks for your quick response. I posted little older code first time but then I corrected it. Please check below mentioned code

void callback(char* topic, byte* payload, unsigned int length);

PubSubClient client(mqtt_server, 1883, callback, espClient);

void setup() { Serial.begin(115200); setup_wifi(); //client.setServer(mqtt_server, 1883); client.subscribe(topic3); }

Best Regards, Hemal Bavishi

From: MartijnvdB [mailto:notifications@github.com] Sent: 17 May 2016 11:32 To: knolleary/pubsubclient pubsubclient@noreply.github.com Cc: Hemal Bavishi hemal.bavishi@avinsystems.com; Author author@noreply.github.com Subject: Re: [knolleary/pubsubclient] MQTT Subscribe not working (#163)

You did not specify that a callback should be executed when a message is received.

In setup(), after you do client.setServer(arg, arg), you specify which callback to execute, as follows:

client.setCallback(callbackName); // callback executed when message received

— You are receiving this because you authored the thread. Reply to this email directly or view it on GitHubhttps://github.com/knolleary/pubsubclient/issues/163#issuecomment-219626975

MartijnvdB commented 8 years ago

Hi,

Did you uncommment the line that says:

_//client.setServer(mqttserver, 1883);

and did you add the following line after that:

client.setCallback(callback); // callback executed when message received

?

hemalbavisi commented 8 years ago

Yes, I commented this line as I’ve added this line on the top -> PubSubClient client(mqtt_server, 1883, callback, espClient);

Isn’t above line serve the same purpose?

Nevertheless, I can try uncommenting this line and also add the line you suggested and will get back to you.

client.setServer(mqtt_server, 1883);

client.setCallback(callback); // callback executed when message received Many Thanks!

MartijnvdB commented 8 years ago

PubSubClient client(mqtt_server, 1883, callback, espClient);

Hm, that should work too, indeed (according to the docs). Haven't used that one yet, myself.

hemalbavisi commented 8 years ago

Thanks. I'll check and revert back to you in few hours.

hemalbavisi commented 8 years ago

Unfortunately it doesn't work. Sometime data appears but most of the time it doesn't. What could be the problem?

edwin-oetelaar commented 8 years ago

Check the data flowing to the server using WireShark. Use a debugger? Write log files? Use brain?

knolleary commented 8 years ago

Any update?

Kerr1st commented 8 years ago

Hi Knolleary, Picking up the issue...Mqtt_Esp8266 example doesn't receive/serial print on inTopic (publishes outTopic fine) nor toggle LED. See Serial Output below. Two other clients connected and receive publish outTopic and published inTopics. Wemos D1 mini is ESP8266 module.

serial output: WiFi connected IP address: 192.168.1.96 Attempting MQTT connection...connected Publish message: hello world #1 Publish message: hello world #2 Publish message: hello world #3 Publish message: hello world #4 Publish message: hello world #5 Publish message: hello world #6 Publish message: hello world #7 Publish message: hello world #8 Publish message: hello world #9 Publish message: hello world #10 Publish message: hello world #11 Publish message: hello world #12 Publish message: hello world #13 Publish message: hello world #14 Publish message: hello world #15

edwin-oetelaar commented 8 years ago

looking at line 92 of the example ; https://github.com/knolleary/pubsubclient/blob/master/examples/mqtt_esp8266/mqtt_esp8266.ino

check the return value of the subscribe call client.subscribe("inTopic");

maybe it gives an error?? ( == false) for some reason.

good luck, Edwin

On Tue, Nov 29, 2016 at 5:40 AM, Kerr1st notifications@github.com wrote:

Hi Knolleary, Picking up the issue...Mqtt_Esp8266 example doesn't receive/serial print on inTopic (publishes outTopic fine) nor toggle LED. See Serial Output below. Two other clients connected and receive publish outTopic and published inTopics. Wemos D1 mini is ESP8266 module.

serial output: WiFi connected IP address: 192.168.1.96 Attempting MQTT connection...connected Publish message: hello world #1 Publish message: hello world #2 Publish message: hello world #3 Publish message: hello world #4 Publish message: hello world #5 Publish message: hello world #6 Publish message: hello world #7 Publish message: hello world #8 Publish message: hello world #9 Publish message: hello world #10 Publish message: hello world #11 Publish message: hello world #12 Publish message: hello world #13 Publish message: hello world #14 Publish message: hello world #15

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or mute the thread.

fdrevet commented 7 years ago

Hi there, here is my experience with ESP8266 (01 and 12 models) and MQTT using PubSubClient.

The publishing works quite well and is also reliable (with an ESP8266-12), but the subscribing is just a real pain (IMO !)... for me the subscribe method mostly returns 0, "randomly" and very few times it returns 1... same behaviour with 3 ESP8266-12 modules...

Note : I'm using "EasyIot Cloud" MQTT server, dunno if it can be the reason ! I'll try a local MQTT server and send the result here.

hudanar commented 7 years ago

Hi there, iam using 2 Wemos D1 R2, 1 for publisher and 1 for subscriber. connected to mosquitto broker on my pc, but everytime publisher publish message, the subscriber got disconneted and reconnecting to the broker, so the subscriber never get the message from the publisher, anyone know how to fix that?

knolleary commented 7 years ago

@hudanar please don't ask your own questions on other issues.

My guess is you are using the same clientid for both clients and they are kicking each other off the broker. Make use you give each client a unique id

hatfieldr commented 7 years ago

Hi Nick I have a similar problem using PubSubClient. It connects to wifi & to MQTT server & publishes fine but does not receive subscribe data. I have an ESP8266-01 connected to Arduino Mega (with level conversions) Code:

#include <WiFiEsp.h>
#include <WiFiEspClient.h>
#include <WiFiEspUdp.h>
//#include "SoftwareSerial.h"
#include <PubSubClient.h>

IPAddress server(192,168,1,xxx);
char ssid[] = "xxxxxxxxx";           // your network SSID (name)
char pass[] = "xxxxxxxxxx";           // your network password
int status = WL_IDLE_STATUS;   // the Wifi radio's status

// Initialize the Ethernet client object
WiFiEspClient espClient;

PubSubClient client(espClient);

//SoftwareSerial soft(2,3); // RX, TX
void setup() {
  // initialize serial for debugging
  Serial.begin(115200);
  // initialize serial for ESP module
  Serial1.begin(115200);
  // initialize ESP module
  WiFi.init(&Serial1);

  // check for the presence of the shield
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present");
    // don't continue
    while (true);
  }

  // attempt to connect to WiFi network
  while ( status != WL_CONNECTED) {
    Serial.print("Attempting to connect to WPA SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network
    status = WiFi.begin(ssid, pass);
  }

  // you're connected now, so print out the data
  Serial.println("You're connected to the network");

  //connect to MQTT server
  client.setServer(server, 1883);
  client.setCallback(callback);
}

//print any message received for subscribed topic
void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);

  Serial.print("] ");
  for (int i=0;i<length;i++) {
   char receivedChar = (char)payload[i]; 
    Serial.print(receivedChar);
    if (receivedChar == '0')
    Serial.println("Off");
    if (receivedChar == '1')
    Serial.println("On");

  }
  Serial.println();
}

void loop() {
  // put your main code here, to run repeatedly:
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect, just a name to identify the client
    if (client.connect("AMega","xxxxxx","xxxxxxxxxxx")) {
      Serial.println("connected");
      // Once connected, publish an announcement...
 //  client.publish("Hello World");
      // ... and resubscribe
      client.subscribe("switch");

    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

This connects to WiFi fine & to an MQTT server running on a raspberry Pi It posts to the Pi but does not receive subscribed messages. I also have an MQTT client on my android phone. This communicates fine with the RPi Again the Arduino can publish to my phone but cannot receive with subscribe

I am not sure where to go next? Any help would be appreciated

Richard

fdrevet commented 7 years ago

Hi Richard,

Your code seems to be OK.

Which MQTT broker are you using on your Raspberry ?

Does the subscribe("switch") call is successfully returning 1 ?

I had a lot of headache making my ESP8266-12 working (mainly with EasyIOT MQTT broker... in fact...) but now it's OK with my Raspberry hosting a Mosquitto MQTT broker.

Best regards,

Florian

2017-01-05 23:13 GMT+01:00 hatfieldr notifications@github.com:

Hi Nick I have a similar problem using PubSubClient. It connects to wifi & to MQTT server & publishes fine but does not receive subscribe data. I have an ESP8266-01 connected to Arduino Mega (with level conversions) Code:

include

include

include

//#include "SoftwareSerial.h"

include

IPAddress server(192,168,1,xxx); char ssid[] = "xxxxxxxxx"; // your network SSID (name) char pass[] = "xxxxxxxxxx"; // your network password int status = WL_IDLE_STATUS; // the Wifi radio's status

// Initialize the Ethernet client object WiFiEspClient espClient;

PubSubClient client(espClient);

//SoftwareSerial soft(2,3); // RX, TX void setup() { // initialize serial for debugging Serial.begin(115200); // initialize serial for ESP module Serial1.begin(115200); // initialize ESP module WiFi.init(&Serial1);

// check for the presence of the shield if (WiFi.status() == WL_NO_SHIELD) { Serial.println("WiFi shield not present"); // don't continue while (true); }

// attempt to connect to WiFi network while ( status != WL_CONNECTED) { Serial.print("Attempting to connect to WPA SSID: "); Serial.println(ssid); // Connect to WPA/WPA2 network status = WiFi.begin(ssid, pass); }

// you're connected now, so print out the data Serial.println("You're connected to the network");

//connect to MQTT server client.setServer(server, 1883); client.setCallback(callback); }

//print any message received for subscribed topic void callback(char topic, byte payload, unsigned int length) { Serial.print("Message arrived ["); Serial.print(topic);

Serial.print("] "); for (int i=0;i<length;i++) { char receivedChar = (char)payload[i]; Serial.print(receivedChar); if (receivedChar == '0') Serial.println("Off"); if (receivedChar == '1') Serial.println("On");

} Serial.println(); }

void loop() { // put your main code here, to run repeatedly: if (!client.connected()) { reconnect(); } client.loop(); }

void reconnect() { // Loop until we're reconnected while (!client.connected()) { Serial.print("Attempting MQTT connection..."); // Attempt to connect, just a name to identify the client if (client.connect("AMega","xxxxxx","xxxxxxxxxxx")) { Serial.println("connected"); // Once connected, publish an announcement... // client.publish("Hello World"); // ... and resubscribe client.subscribe("switch");

} else { Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); // Wait 5 seconds before retrying delay(5000); }

} }

This connects to WiFi fine & to an MQTT server running on a raspberry Pi It posts to the Pi but does not receive subscribed messages. I also have an MQTT client on my android phone. This communicates fine with the RPi Again the Arduino can publish to my phone but cannot receive with subscribe

I am not sure where to go next? Any help would be appreciated

Richard

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/knolleary/pubsubclient/issues/163#issuecomment-270772904, or mute the thread https://github.com/notifications/unsubscribe-auth/AM7O1fCLdDv-MQBBbESHnJZflsxeg8duks5rPWrsgaJpZM4Ifkl7 .

hatfieldr commented 7 years ago

Hi Florian Thanks for replying I am using a Mosquitto MQTT broker (1.4.10) on the RPi (3) It's part of the emonpi software from the OpenEnergyMonitor group. The arduino sketch publishes fine to the RPi and to the client on my android phone (MQTT Client App) The phone communicates both ways with the RPi But the arduino shetch does not appear to receive anything from either my phone or the RPi with client.subscribe("") The arduino stays "connected" but nothing happens! It does automatically disconnect after about 30 seconds & then reconnects to the MQTT broker

I am at a loss as to what to try next! Any suggestions gratefully received!

Regards

Richard

fdrevet commented 7 years ago

Hi Richard,

I'm using Mosquitto without any issue (Raspberry B model 2) I had a lot of problems with random connections and subscriptions, but it was coming from my Wifi router (Livebox, just a shame) now I'm using a WRT54GL and it works like a charm. => dunno what Wifi access point you're using but I guess you're connecting to your raspberry through your Wifi router ? Did you tried to connect from your phone (wifi access point) for exemple ? (you will need a NAT rule to access it from the outside)

As I previously asked it to you, did you checked the subscribe("switch") return ? (should be 0 if it don't succeed to subscribe) Also, did you tried to make a retry logic ? (I think the subscribe method should fails)

Best regards,

Florian

hatfieldr commented 7 years ago

Hi Florian

I have a BT router, all my current experiments are on my home network, I don't think its a router problem. The mosquitto server on my Pi 3 seems to work fine with other devices (eg the MQTT client on my android phone) client.subscribe("switch",0) returns 1 so I guess "subscribe" may be working & the problem is with callback? no messages for topic "switch" seem to be received I have tried lots of different message formats

would love to solve it! Its holding up my project!

Regards

Richard

fdrevet commented 7 years ago

Hi Richard,

I was asking you about the router because my smartphones was perfectly working (connect, subscribe, publish), but my ESP8266 was rarely and randomly working.

It's very strange that subscribe() returns 1 and if you don't receive anything on callback method.

I'm calling setCallback() before setServer(), don't know if it can change anything...

You seems to have a working broker, but have you tried mosquitto_pub mosquitto_sub batch calls directly on your Raspberry ?

If you want, I can send to you my working code by mail, if it can helps.

Florian

hatfieldr commented 7 years ago

Hi Florian My sketch is based on one of the examples so I guess it has the right format. The broker on the Pi seems to be working fine .... it communicates with the client on my android phone both ways... I wondered if there was any way of "sniffing" communication with the ESP8266? when I fist connected the ESP to my arduino mega I used 10K & 20K resitors in the voltage dividers on the mega output lines ..... this resulted in very erratic transmission at 115200 baud but when I used 1k & 2K resistors it connected to wifi & the MQTT broker fine....

I'm not sure what to try next....

Regards Richard

slavino commented 7 years ago

Hi, if your issues are only HW related give it a try with Logic Level converter 3V3/5V (example: http://www.ebay.com/itm/2-Channel-Way-Bi-directional-Logic-Level-Shifter-Converter-5V-3-3V-TTL-Module-/121736138032?var=&hash=item1c580a0d30:m:mGYrmVBtrJ153d9DsH5Ld6g). ArduinoMega has 5V logic and ESP8266 should be 3V3 only.

hatfieldr commented 7 years ago

Hi I do know about the different voltages! my issues are not related to level shifting I originally used resistive dividers to shit levels, I now use a level shifter. It made no difference. The arduino communicates fine with the ESP. It logs on to the network & the MQTT broker It publishes fine & subscribe() returns 1 but no messages are received for the subscribed topic....

slavino commented 7 years ago

Ah, got it now - sorry for misunderstanding... Then off-topic reaction: What about bypassing the issue for now with regular querying the channel for retained messages?

hatfieldr commented 7 years ago

Update 2

command line publish on the Rpi works fine $mosquitto_pub -u 'xxxxx' -P 'xxxxxxx' -t 'switch' -m '1switchon' This is received on my android mqtt client but not the arduino

I have tried installing mosquitto on my PC.... The results are exactly the same!

I have tried an ESP8266-12 with the Mega with the same result It connects to the WiFi network & to the MQTT broker, It publishes fine client.subscribe() returns true but no messages are received

Desperate for an answer............ Any help appreciated.....,......

Richard

tororm commented 7 years ago

Hi @hatfieldr ,

I was tidying up some working code and I experienced the same issue. I believe I'm on to something, but it's too late for me to investigate further. My mqtt payload looks like this: {"desired_hysterisis":0,"desired_temp": 50,"desired_humidity":20,"desired_FanOn":off,"desired_FanBreak":5.0}

However, try as I may, the callback is not entered. Subscribe Status is 1.

I then change the payload to something simple like 'Hello'.

It arrives!

Hoping this helps. I will do some more testing in coming days.

Edit: scratch that. Changing the QOS to 1 and waiting for a few loops results in the message arriving.

hatfieldr commented 7 years ago

I solved the problem by calling: if (!client.connected()) reconnect(); & client.loop(); every 100 ms instead of every loop If you are not flashing the code to the ESP but are using an arduino connected to the ESP via serial I think the problem is calling these functions every loop causes the serial interface to be overwhelmed with status messages blocking the incoming message. I am a newbie programmer especially with the ESP & MQTT so I'm not sure................ But my setup is now working (After a week of tearing my hair out!!) Richard

anupam19 commented 7 years ago

Have you used escape characters for "" ? ie \"desired_temp\"

On Mon, Jan 30, 2017 at 5:20 PM, tororm notifications@github.com wrote:

Hi @hatfieldr https://github.com/hatfieldr ,

I was tidying up some working code and I experienced the same issue. I believe I'm on to something, but it's too late for me to investigate further. My mqtt payload looks like this: {"desired_hysterisis":0,"desired_temp": 50,"desired_humidity":20," desired_FanOn":off,"desired_FanBreak":5.0}

However, try as I may, the callback is not entered. Subscribe Status is 1.

I then change the payload to something simple like 'Hello'.

It arrives!

Hoping this helps. I will do some more testing in coming days.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/knolleary/pubsubclient/issues/163#issuecomment-276043807, or mute the thread https://github.com/notifications/unsubscribe-auth/AH9rt1_kR-jVIamRDcl2A3H_OV70wMMhks5rXc6RgaJpZM4Ifkl7 .

anupam19 commented 7 years ago

Yup, without a reconnect function, connection drop happens with frequent streaming. It is due to hardware failure. Can not process big payloads at such faster rate

On Mon, Jan 30, 2017 at 6:08 PM, hatfieldr notifications@github.com wrote:

I solved the problem by calling: if (!client.connected()) reconnect(); & client.loop(); every 100 ms instead of every loop If you are not flashing the code to the ESP but are using an arduino connected to the ESP via serial I think the problem is calling these functions every loop causes the serial interface to be overwhelmed with status messages blocking the incoming message. I am a newbie programmer especially with the ESP & MQTT so I'm not sure................ But my setup is now working (After a week of tearing my hair out!!) Richard

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/knolleary/pubsubclient/issues/163#issuecomment-276052780, or mute the thread https://github.com/notifications/unsubscribe-auth/AH9rtwr2yXa6FXvI7ybhR5QSsMeEyP2iks5rXdnfgaJpZM4Ifkl7 .

paulovitoriano commented 7 years ago

I have the same problem and the sketch from @hatfieldr

I put client.loop() every 100 ms instead of every loop but I still do not get anything than subscribe. Only Publish work.

I use #mosquitto_sub -d -t test/# and receive all payloads perfect from Rasbberry, Android App and Arduino with ESP8266 using WiFiEsp.

I test with mosquitto send like #mosquitto_pub -d -t test/V_HUM -m "68" by example and receive at Raspberry and Android App but not in Arduino.

I try a lot of things, but I do not know more what to do...

hatfieldr commented 7 years ago

Hi You need to call if (!client.connected()) reconnect(); every 100 ms as well........

paulovitoriano commented 7 years ago

Thank you for quickly reply

Now work using delay(100) after client.loop() But if you use something like below not work.

unsigned long now = millis(); if (now - lastLoop > 100) { client.loop(); lastLoop = now;
}

However it seems unstable because sometimesit does not receive the package.

Thank a lot.

hatfieldr commented 7 years ago

delay(100); delays the whole loop your code only delays : client.loop(); have you delayed: if (!client.connected()) reconnect(); ?

boguslawb commented 7 years ago

Put client.loop() after each client.subscribe and check if each client.subscribe returned true. I think this issue is about that .

stefanbode commented 7 years ago

hi @boguslawb . the client.loop() after the subscribe is a good idea. But it will not work with retained messages. I have 4 messages and subscribe to .../#. All 4 messages are sent (mosquitto.log) but only the first message is captured through the callback(). All other messages are gone. It works afterwards if one message after another is coming in. I'm using a slightly modified version of PubSubClient.cpp. Added a yield(); in line 214.

corneyl commented 7 years ago

I also had a problem with subscribing to a topic, after trying a lot of things I think my problem was that the signature of the callback I passed was not right. I'm now using:

mqttClient = new PubSubClient(tcpClient);
mqttClient->setCallback(
    [this](char* topic, uint8_t* payload, unsigned int length) -> void {
      // handle message
    }
);

No errors were generated when I was using another signature.

(@hemalbavisi please use triple backticks (```) around multiline code, now it's quite hard to read)

yoran112 commented 7 years ago

In my case it had to do with the message size.

The maximum message size, including header, is 128 bytes by default. This is configurable via MQTT_MAX_PACKET_SIZE in PubSubClient.h

confusedtoo commented 7 years ago

Don't know if this thread is still alive but here goes. I made a discovery in the C++ library that it seems that the variables that should be localized in functions aren't. For instance the "topic" variable is used in both subscribe and publish routines, well you subscribe to topic "out" and then call publish right after and it overwrites the topic variable to "in". This could be a bug in the esp8266 libraries??? Net effect you subscribe to topic "out" and the 1st publish changes your subscription topic to "in".

stefanbode commented 7 years ago

Haven’t seen this behavior in production. The only bug is that if you subscribe the a # topic you only get the FIRST message send from the broker. Others got wiped for whatever reason. Maybe the broker send it to fast. anyhow the error only happen at the first subscribe, if there are two or more keys retained.

confusedtoo commented 7 years ago

Thanks I looked further at other parts of the pgm and found that it was the buffer size, down in the .h file in the src dir that was way too small. It was over writing the topic but only for memory space problems.

stefanbode commented 7 years ago

which of the variables are you referencing? Changing MQTT_MAX_PACKET_SIZE is quite common. Also to shorten the MQTT_SOCKET_TIMEOUT can make sense. I do not find a specific value for the length of the topic.

confusedtoo commented 7 years ago

It was the packet size, my MQTT was around 250 depending on vars. Now set to 512 all is happy till I get carried away with more variables. Thanks

sunnydevtale commented 7 years ago

I am using ESP8266 to publish and subscribe the the data on RPi mosquito broker. I did not gone through all comments mentioned above. I am able to publish data to mosquito broker but while subscribing, the data callback function not working or called and data not displayed on serial monitor.

Finally I have solved this problem. If you are using the client.loop(); function in code, use dalay(100) after client.loop() function code line. I think to subscribe message takes some delay to run callback function.

If this solution works fine let me know. Happy Arduino programming.

epicycler commented 6 years ago

I have ESP8266 with pubsub. Arduino IDE. No Arduino hardware, just ESP8266 ESP-01.

If both publish and subscribe then nothing useful in callback. Device resets frequently. If just subscribe then some hieroglyphics in callback. Inside function boolean PubSubClient::loop() in pubsub I can successfully trace received messages as far as where callback is called. Serial.write for each character in topic and payload. eg. (buffer is 255, I changed the message size.

                    Serial.print("topic ");
                    for (int i=0; i<tl; i++) {
                        Serial.write(topic[i]);
                    }
                    Serial.println(" ");

and (because I don't know the length of payload)

                        Serial.print("payload ");
                        for (int i=0; i<255-tl; i++) {
                            Serial.write(payload[i]);
                        }
                        Serial.println(" ");

Uncomment callback in pubsub and in my sketch the topic can be printed. However, length is consistently 5 and payload "not human readable".

A difference between topic and payload is that topic is char* and payload is uint8_t. Probably red herring. But keep in back of mind as similar problems to what we are seeing occur in pubsub when using arduinojson-master to prepare json payload and publish.

Picking up on confusedtoo's comments about scope (whether variables are persistent outside the function in which they are declared) I added static to the declaration of both payload and topic in pubsub function boolean PubSubClient::loop() thus:-

static uint8_t *payload;
static char *topic = (char*) buffer+llen+2;

buffer is already declared global.

This lets me successfully use the following in my sketch callback function:-

 Serial.println(topic);
 for (int i=0; i < 50; i++) {
   Serial.write(payload[i]);    
 }

The device seems to maintain its connection more reliably.

FWIW I met similar problem (scope) a couple of weeks ago. A library which compiled and ran on Arduino Uno and Mega hung on a Teensy. Its quite possible that people are getting different results from pubsub on different hardware.

I haven't yet figured out why the length of the payload provided by callback is always 5.

I also haven't yet tested with publishing and subscribing at the same time. Nor do I understand why the message is frequently garbled when first received into buffer. Experience suggests there's more than one problem with pubsub on ESP8266.

I'm not a C++ programmer. I have limited understanding.

epicycler commented 6 years ago

after some more testing my ESP8266 sketch now both publishes and subscribes. Note that with Arduino IDE (on Win 10) sketches compiled for ESP8266 (Adafruit HUZZAH) have different outcome to same sketch compiled for Uno or Mega. In ESP8266 variables declared inside a function do not persist after completion of function.

The problem occurs here in callback. It applies generally to return from any function.

following are required changes to PubSubClient.cpp

line 304 declare payload as static static uint8_t payload;

line 313 declare topic as static static char topic = (char*) buffer+llen+2;

add line 314 declare new variable plen as static static uint8_t plen = 0;

add line 319 assign value (calculated length of payload) to plen plen = len-llen-3-tl-2;

change line 320 callback with new variable plen callback(topic,payload,plen);

add line 331 assign value (calculated length of payload) to plen plen = len-llen-3-tl;

change line 332 callback with new variable plen callback(topic,payload,plen);

Thanks for very useful library. I've now tested publishing at 1000 messages per second and receive occasional subscribed messages with mosquitto on raspberry pi 3.

knolleary commented 6 years ago

@epicycler much easier if you can propose changes as a pull request

epicycler commented 6 years ago

@knolleary thanks. I'm totally new to Github and all things Linux. Its very foreign to me. Not your fault, but when I read the info on pull request I left with absolutely no idea. Common problem for me, lots of info on how but not a lot about why. I'll create a pull request. How does that eventually result in changes to the library? I have a totally unrelated library which is worthy of publishing but absolutely no idea what the whole process looks like.

knolleary commented 6 years ago

@epicycler there's no guarantees if/when these changes will get into the library. You'll see there are lots of outstanding PRs against this library, all waiting for me to find the time and energy to review and decide what to merge. The point of a PR is it puts the proposed changes into context.

GitHub makes it quite easy to do a pull request on a single file. Go to that files page (https://github.com/knolleary/pubsubclient/blob/master/src/PubSubClient.cpp), click the edit button in the top right and it'll walk you through.

epicycler commented 6 years ago

well that was interesting. I expected to see my pull request appear in the list of pull requests.

how do I delete epicycler/pubsubclient?