256dpi / arduino-mqtt

MQTT library for Arduino
MIT License
1.01k stars 232 forks source link

Unable to connect to broker when used with Portenta H7 #271

Open Twinkle299 opened 2 years ago

Twinkle299 commented 2 years ago

I have been using this library with both MKR NB1500 and MKR Zero + Ethernet Shield with a lot of success,

I am attempting to use a Portenta H7, using EthernetClient i can access the network fine(i perform an http get etc) however using this EthernetClient with with the mqttClient it fails to connect to the broker (this same approach works perfectly with MKR boards).

Has anyone successfully used the library along with a Portenta ?

InconceivableDuck commented 1 year ago

I ran into this problem when passing a static memory buffer (from SDRAM) to MBED's Thread constructor. When not passing a buffer, the library connects successfully. The issue isn't related to this library. Arduino's WiFiClient, for me, won't connect to anything inside a thread when using a static memory buffer.

Edit: I got this to work by passing a pointer to the WiFiClient through the Thread's start function.

void setup() {

  ...

  threadMQTT = new Thread(osPriorityNormal, 256 * 1024, mqttThreadBuffer, nullptr);
  threadMQTT->start(callback(loopMQTT, &wifiClient));

  ...

}

void loopMQTT(WiFiClient *wifiClient) {

  ...

  mqttClient.begin(LOSANT_BROKER, LOSANT_PORT, *wifiClient);

  ...
}
InconceivableDuck commented 1 year ago

Update to the above, I believe the underlying issue is that connect will always fail if it's attempted before WiFi has been connected. I noticed the underlying MbedClient only attempts to ever create the socket once. If connect is called after WiFi is connected is works. If connect is called before WiFi is connected, it creates and keeps trying to use a socket that will never work.

My solution was to call stop on WiFiClient inside the loop that's attempting to connect to the MQTT broker. The stop function sets the underlying socket back to null, so that it's created again on any future connect attempts.

while(!mqttClient.connected()) {

  Serial.println("Connecting to MQTT broker...");

  // There's an issue with MbedClient initializing the underlying
  // socket before connection is established (e.g. WiFi). Need to
  // stop on each attempt to force a new socket to be created.
  context->client->stop();

  mqttClient.connect(LOSANT_DEVICE_ID, LOSANT_ACCESS_KEY, LOSANT_ACCESS_SECRET);
  Serial.println(mqttClient.lastError());
  ThisThread::sleep_for(1000);
}
256dpi commented 1 year ago

@InconceivableDuck Thanks for the update! However, I'm not sure what we should do about it. We could make a precautionary call to client->stop() on every connect(), but this could trigger other bugs in network implementations that do not expect a call to stop before connect... Therefore, It seems to me that this is better fixed in MbedClient than in this library.

razvanphp commented 9 months ago

@InconceivableDuck thanks for the tip, this solved my problem too!

void connect() {

  while (!mqttClient.connect("arduino")) {
    // There's an issue with MbedClient initializing the underlying
    // socket before connection is established (e.g. WiFi). Need to
    // stop on each attempt to force a new socket to be created.
    ethClient.stop();

    Serial.print(".");
    delay(1000);
  }
...
}

We switched from MKR 1010 + ETH shield to Portenta H7 Light + ETH shield and we noticed that broker connects at startup, but when taking the cable off and putting it back on, network comes back, but mqttClient does not reconnect.

Any suggestion on how to create an issue to get this fixed in MbedClient? I don't really understand the details to explain it....

Thank you! R