Go Down

Topic: MQTT - Wifi101 : buffer full problem with object programming (Read 332 times) previous topic - next topic

olivchemin

Hi,

I want to write a program that should communicate to a MQTT server and send various sensors data. I was testing the communication part between the wifi and the MQTT Server.

Using the ArduinoMqtt library, it works well if i just modify a little bit the example with my personal parameters. This example sends a test message every seconds and works perfectly :

Code: [Select]

// This example uses an Arduino/Genuino Zero together with
// a WiFi101 Shield or a MKR1000 to connect to shiftr.io.
//
// IMPORTANT: This example uses the new WiFi101 library.
//
// You can check on your device after a successful
// connection here: https://shiftr.io/try.
//
// by Gilberto Conti
// https://github.com/256dpi/arduino-mqtt

#include <WiFi101.h>
#include <MQTT.h>

const char ssid[] = "ssid";
const char pass[] = "password";

WiFiClient net;
MQTTClient client;

unsigned long lastMillis = 0;

void connect() {
  Serial.print("checking wifi...");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(1000);
  }

  Serial.print("\nconnecting...");
  while (!client.connect("client_id", "user", "password")) {
    Serial.print(".");
    delay(1000);
  }

  Serial.println("\nconnected!");

  client.subscribe("/hello");
  // client.unsubscribe("/hello");
}

void messageReceived(String &topic, String &payload) {
  Serial.println("incoming: " + topic + " - " + payload);
}

void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, pass);

  // Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino.
  // You need to set the IP address directly.
  client.begin("server_url.com", net);
  client.onMessage(messageReceived);

  connect();
}

void loop() {
  client.loop();

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

  // publish a message roughly every second.
  if (millis() - lastMillis > 1000) {
    lastMillis = millis();
    client.publish("/hello", "esnqerbw");
  }
}




To keep the code as clear as possible (I am used to object oriented programming), I want to make a class that would have to deal with all the MQTT part (sending data, receiving commands from server, getting parameters from FlashStorage, etc...). But then I made just the same program but with a MQTT wrapper object :

the .ino file :
Code: [Select]

// This example uses an Arduino/Genuino Zero together with
// a WiFi101 Shield or a MKR1000 to connect to shiftr.io.
//
// IMPORTANT: This example uses the new WiFi101 library.
//
// You can check on your device after a successful
// connection here: https://shiftr.io/try.
//
// by Gilberto Conti
// https://github.com/256dpi/arduino-mqtt

#include <WiFi101.h>
#include <MQTT.h>

#include "MqttWrapper.h"

const char ssid[] = "ssid";
const char pass[] = "password";

WiFiClient net;
MQTTClient client;
MqttWrapperClass MqttWrap(client, net);


void setup() {
 MqttWrap.setup();
}

void loop() {
 MqttWrap.loop();
}



the MqttWrapper.h :
Code: [Select]

// MqttWrapper.h

#ifndef _MQTTWRAPPER_h
#define _MQTTWRAPPER_h

#if defined(ARDUINO) && ARDUINO >= 100
 #include "arduino.h"
#else
 #include "WProgram.h"
#endif

#include <WiFi101.h>
#include <MQTT.h>

class MqttWrapperClass
{
 private:
 MQTTClient _client;
 WiFiClient _netClient;
 int _lastMillis;

 public:
 MqttWrapperClass();
 MqttWrapperClass(MQTTClient &client, WiFiClient &netClient);

 void connect();

 void setup();

 void loop();

 void init();
 void messageReceived(String & topic, String & payload);
};

extern MqttWrapperClass MqttWrapper;

#endif




The MqttWrapper.cpp :
Code: [Select]

//
//
//

#include "MqttWrapper.h"

MqttWrapperClass::MqttWrapperClass()
{
}

MqttWrapperClass::MqttWrapperClass(MQTTClient &client, WiFiClient &netClient)
{
 this->_client = client;
 _netClient = netClient;
}

void MqttWrapperClass::connect()
{
 Serial.print("checking wifi...");
 while (WiFi.status() != WL_CONNECTED) {
 Serial.print(".");
 delay(1000);
 }

 Serial.print("\nconnecting...");
 while (!this->_client.connect("client_id", "user", "passwd")) {
 Serial.print(".");
 delay(1000);
 }

 Serial.println("connected!");

 this->_client.subscribe("/hello");
 // this->_client.unsubscribe("/hello");
}

void MqttWrapperClass::setup()
{
 WiFi.begin("ssid", "password");

 // Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino.
 // You need to set the IP address directly.
 this->_client.begin("server_url", _netClient);
 this->_client.onMessage(messageReceived);

 connect();
}

void MqttWrapperClass::loop()
{
 if (!this->_client.connected()) {
 this->connect();
 }

 // publish a message roughly every second.
 if (millis() - _lastMillis > 2000) {
 _lastMillis = millis();
 this->_client.publish("/hello", "esnqerbw");
 }
}

void MqttWrapperClass::init()
{
 

}

void MqttWrapperClass::messageReceived(String &topic, String &payload) {
 Serial.println("incoming: " + topic + " - " + payload);
}


MqttWrapperClass MqttWrapper;




With this way of coding, it works for a few messages to send, but it fails after 2 ou 3 successful messages upload. I get then an error in the WiFisocket.cpp in the write function with a SOCK_ERR_BUFFER_FULL error :

Code: [Select]

size_t WiFiSocketClass::write(SOCKET sock, const uint8_t *buf, size_t size)
{
 m2m_wifi_handle_events(NULL);

 if (_info[sock].state != SOCKET_STATE_CONNECTED) {
 return 0;
 }

#ifdef CONF_PERIPH
 // Network led ON (rev A then rev B).
 m2m_periph_gpio_set_val(M2M_PERIPH_GPIO16, 0);
 m2m_periph_gpio_set_val(M2M_PERIPH_GPIO5, 0);
#endif

 sint16 err;

 while ((err = send(sock, (void *)buf, size, 0)) < 0) {
 Serial.println("SocketWrite error");
 // Exit on fatal error, retry if buffer not ready.
 if (err != SOCK_ERR_BUFFER_FULL) {
 size = 0;
 break;
 } else if (hif_receive_blocked) {
 size = 0;
 break;
 }
 m2m_wifi_handle_events(NULL);
 }

#ifdef CONF_PERIPH
 // Network led OFF (rev A then rev B).
 m2m_periph_gpio_set_val(M2M_PERIPH_GPIO16, 1);
 m2m_periph_gpio_set_val(M2M_PERIPH_GPIO5, 1);
#endif

 return size;
}


This never happens if I put the code in the .ino file, why ? I tried the same config with a MKR1400 and I didn't have this kind of problem.

Any idea why ?


desvdp

Hi, I'm facing a similar problem; did you figure out what caused this ?
Thanks !

Go Up