Go Down

Topic: MQTT - Wifi101 : buffer full problem with object programming (Read 423 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 !

jisoojeong


Hello! I think these can be simillar problem that I suffered before


refer this one that I suffered : https://forum.arduino.cc/index.php?topic=582604.0


if you think it is simillar with your problem, I think you need to modify your code


like data field in your cloud


I found that a lot of data sending can make problem


or check your firmware updater (check your cloud "end point". If mqtts://~~~ -> ~~~:8883

If mqtts.~~~-> mqtts.~~~ to be one part "3" in your updater gui)


before write your mqtts end point, please remove the things that is written on part 3

and after it, you can write your end point and update firmware

Sometimes, you must check your cloud tutorial

because there are some more specific things that they supports on website tutorial

some cloud can request to make openssl (.pem or .cert...)

Compare clouds and choose the one that can be seemed optimal to your purpose!


++If you need to use "mqtt"(not mqtts),  check your cloud supports it

[mqtt: 1883 port, mqtts: 8883 port. you can simulate its connection on mosquitto/mqtt.fx ~~~[mqtt

broker]]


It's just my think just refer it!!(I don't think it is answer!so just refer it to your program!)

enjoy your mkr1000!



Go Up