adafruit / Adafruit_MQTT_Library

Arduino library for MQTT support
MIT License
571 stars 292 forks source link

Error Connection failed #160

Open thesun93pp opened 4 years ago

thesun93pp commented 4 years ago

Adafruit_MQTT library is awesome but i have got a problem with it. I use it in Arduino with NodeMCU (ESP8266). Everything is okey with example code. (TLS connection). Everything is also ok when i put topic direct value: "sometopic/abc/adbc" to input param.


//Connect successfuly when i use:
  GLB_MQTTClient = temMQTT;
  Adafruit_MQTT_Publish *temPub = new Adafruit_MQTT_Publish(GLB_MQTTClient, "pubTopic", MQTT_QOS_1);
  Adafruit_MQTT_Subscribe *temSub = new Adafruit_MQTT_Subscribe(GLB_MQTTClient, "subTopic", MQTT_QOS_1);

But My program has to check some configs to get MQTT topic from EEPROM so it can't assign TOPIC when initialize variable at head of file. So i created new pointer for new value.

I got Connection failed when i use This is my basic code:


WiFiClientSecure GLB_secureClient;
//Init with default value, cuz the library does not have default constructor
Adafruit_MQTT_Client *GLB_MQTTClient = new Adafruit_MQTT_Client(NULL, NULL, NULL, NULL, NULL, NULL);
Adafruit_MQTT_Publish *GLB_MQTT_Publish = new Adafruit_MQTT_Publish(NULL, NULL, MQTT_QOS_1);
Adafruit_MQTT_Subscribe *GLB_MQTT_Subcribe = new Adafruit_MQTT_Subscribe(NULL,NULL,MQTT_QOS_1);

void initNormalConnection()
{
  printf("\n\nAddress of GLB_secureClient: %p\n", &GLB_secureClient);
  printf("Address of GLB_MQTTClient: %p\n", GLB_MQTTClient);
  printf("Address of GLB_MQTT_Publish: %p\n", GLB_MQTT_Publish);
  printf("Address of GLB_MQTT_Subcribe: %p\n", GLB_MQTT_Subcribe);

  GLB_secureClient = WiFiClientSecure();
  GLB_secureClient.setFingerprint(FINGER_PRINT);

  Adafruit_MQTT_Client *temMQTT = new Adafruit_MQTT_Client(&GLB_secureClient, BROKER_HOST, BROKER_PORT);

  GLB_MQTTClient = temMQTT;
  Adafruit_MQTT_Publish *temPub = new Adafruit_MQTT_Publish(GLB_MQTTClient, pubTopic, MQTT_QOS_1);
  Adafruit_MQTT_Subscribe *temSub = new Adafruit_MQTT_Subscribe(GLB_MQTTClient, subTopic, MQTT_QOS_1);

  GLB_MQTT_Publish = temPub;
  GLB_MQTT_Subcribe = temSub;
  GLB_MQTT_Subcribe->setCallback(MQTTCtrCallback);
  GLB_MQTTClient->subscribe(GLB_MQTT_Subcribe);

  printf("\n\nAddress of GLB_secureClient: %p\n", &GLB_secureClient);
  printf("Address of GLB_MQTTClient: %p\n", GLB_MQTTClient);
  printf("Address of GLB_MQTT_Publish: %p\n", GLB_MQTT_Publish);
  printf("Address of GLB_MQTT_Subcribe: %p\n", GLB_MQTT_Subcribe);

  PRINTLN("\ninitNormalConnection");
}

void MQTTConnect()
{
  int8_t ret;
  // Stop if already connected.
  PRINTLN("MQTTConnect");
  if (GLB_MQTTClient->connected())
  {
    PRINTLN("connected");
    return;
  }
  PRINTLN("not connected");

  if (stateSmartConfig || WiFi.status() != WL_CONNECTED)
  {
    return;
  }
  PRINTLN("Connecting to MQTT... ");
  uint8_t retries = 3;
  ret = GLB_MQTTClient->connect();
  PRINT("Connect MQTT result: ");
  PRINTLN(ret);
  while (ret != 0)
  { // connect will return 0 for connected
    ERR_PRINTLN(GLB_MQTTClient->connectErrorString(ret));
    DEBUG_PRINTLN("Retrying MQTT connection in 10 seconds...");
    GLB_MQTTClient->disconnect();
    delay(10000);
    retries--;
    if (retries == 0)
    {
      // basically die and wait for WDT to reset me
      return;
    }
  }
  Serial.println("MQTT Connected!");
}

void setup(){
    initNormalConnection();
 }

void loop()
{

//do somethings

  MQTTConnect();
  GLB_MQTTClient->processPackets(10000);
  if (!GLB_MQTTClient->ping())
  {
    GLB_MQTTClient->disconnect();
  }
}

Variable's addresses was changed. The output of the address:

Address of GLB_secureClient: 0x3ffef170 Address of GLB_MQTTClient: 0x3fff167c Address of GLB_MQTT_Publish: 0x3fff17e4 Address of GLB_MQTT_Subcribe: 0x3fff17f4

Address of GLB_secureClient: 0x3ffef170 Address of GLB_MQTTClient: 0x3fff27ac Address of GLB_MQTT_Publish: 0x3fff220c Address of GLB_MQTT_Subcribe: 0x3fff2914

What could be the problem?

SheepKnight commented 4 years ago

In the Adafruit_MQTT.h header file, could you please uncomment MQTT_DEBUG. Do not post the output from serial here, but you could probably guess more about your problem with it

natrya commented 4 years ago

I have an idea extend the library the problem is when you declare before setup is can't change the value.

what you need to save into/load from eeprom in my point of view is username, key and feeds

see the source code in https://github.com/adafruit/Adafruit_MQTT_Library/blob/master/examples/mqtt_esp8266/mqtt_esp8266.ino

in declarative part put the server object definition without username and key

Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT); Adafruit_MQTT_Publish photocell = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/photocell"); Adafruit_MQTT_Subscribe onoffbutton = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/onoff");

in setup() you can set username and key through connect() public method, which is you can retrieve from eeprom

//retreive username and key from eeprom //example 0 - 19 is username, 20 - 79 is key String usern ,keyn; char username[21], key[61]; for (int i = 0; i < 20; i++) { username[i] = EEPROM.read(i); i++; } // put null as end of string username[20]='\0'; for (int i = 20; i < 80; i++) { key[i-20] = EEPROM.read(i); i++; } key[60]='\0';

usern = String(username); keyn = String(key);

const char usernew = usern.c_str(); const char keynew = keyn.c_str(); mqtt.connect(usernew, keynew);

next to make feeds become changeable on setup()

u need to add method on Adafruit_MQTT.h and Adafruit_MQTT.cpp open header first add on line 280

class Adafruit_MQTT_Subscribe {
273 public:
274 Adafruit_MQTT_Subscribe(Adafruit_MQTT mqttserver, const char feedname, uint8_t q=0);
275
276 void setCallback(SubscribeCallbackUInt32Type callb);
277 void setCallback(SubscribeCallbackDoubleType callb);
278 void setCallback(SubscribeCallbackBufferType callb);
279 void setCallback(AdafruitIO_MQTT *io, SubscribeCallbackIOType callb);
*280 void setFeeds(const char feed);**

open cpp add at the end of file void Adafruit_MQTT_Subscribe::setFeeds(const char *feed) {
topic = feed;
}

now in your setup() before mqtt.connect(usernew, keynew); set subscribe feeds feedsnew you can do same with usernew onoffbutton.setFeeds(feedsnew);

you can do same with subscribe for publish part.

let's make apps with more flexible

spdi commented 4 years ago

You are misunderstanding how to use heap. You instantiate GLB_MQTTClient, GLB_MQTT_Publish, GLB_MQTT_Subcribe twice on a heap, and so you have small memory leak, you lost pointers to classes instatiated in declarative section. For the first declare only a pointers and then instantiate an object in a initNormalConnection().

code excerpt:

`WiFiClientSecure GLB_secureClient; //Init with default value, cuz the library does not have default constructor Adafruit_MQTT_Client GLB_MQTTClient; Adafruit_MQTT_Publish GLB_MQTT_Publish; Adafruit_MQTT_Subscribe *GLB_MQTT_Subcribe;

void initNormalConnection() { printf("\n\nAddress of GLB_secureClient: %p\n", &GLB_secureClient); printf("Address of GLB_MQTTClient: %p\n", GLB_MQTTClient); printf("Address of GLB_MQTT_Publish: %p\n", GLB_MQTT_Publish); printf("Address of GLB_MQTT_Subcribe: %p\n", GLB_MQTT_Subcribe);

GLB_secureClient = WiFiClientSecure(); GLB_secureClient.setFingerprint(FINGER_PRINT);

GLB_MQTTClient = new Adafruit_MQTT_Client(&GLB_secureClient, BROKER_HOST, BROKER_PORT); GLB_MQTT_Publish = new Adafruit_MQTT_Publish(GLB_MQTTClient, pubTopic, MQTT_QOS_1); GLB_MQTT_Subcribe = new Adafruit_MQTT_Subscribe(GLB_MQTTClient, subTopic, MQTT_QOS_1);

...`