Troubleshooting Arduino sending MQTT client.connect() returns false

by electronichamsters

Solution:  Thanks to Peter Hardy and Jan-Piet Mens from the OpenHAB discussion group for pointing out the solution.  I moved the client.connect() call to the setup routine instead of calling it every time I need to send an MQTT message.  That fixed the problem.  I’ll keep this post around for reference.

—————- original post ——————————-

After getting really excited about my wireless Arduino sensor setup, I’ve found some reliability issues.  To recap, I’m using an ethernet connected Arduino to relay some wireless sensor data to a MQTT server sitting on the same LAN.  It seemed to work pretty reliably, but recently I’ve discovered that sometimes the ethernet Arduino gets into a funk and can’t publish MQTT messages.  The problem is that client.connect() is returning false, and continuously returning false for multiple minutes.  It’s been hard to find a pattern why it’s doing that.  I think client.connect() is part of the ethernet.h library, but not positive.

When there is new data, the sketch loops until clinet.connect() returns true, before going ahead with the MQTT pub.  Sometimes it takes many hundred cycles for it to finally return true and I see the MQTT data using Mosquitto.  This could be 10 seconds.  Other times the data sits in the while loop until finally new data is sent and this data never got sent.

I’ve also verified that the problem isn’t with wireless transmission not being seen by the RFM Arduino gateway.  The 915MHz signal really does make it to the RFM Arduino, and is successfully I2C-ed to the ethernet Arduino.  The problem seems to be narrowly focused on the client.connect() returning false for minutes at a time.

Things I’ve tried:  different router, different ethernet shield (but still Wiznet 5100).  Usually the first transmission after a reboot of the Arduino ethernet gateway works.

Here’s the code – please excuse the formatting.  Use this link to see better formatting:

http://paste.ofcode.org/3bFnJEC5FxVLUqhhuSEEQFS

———————————————————————————–

#include <SPI.h>
#include <Ethernet.h>
#include <Wire.h>
#include <PubSubClient.h>

//I2C receive device address
const byte MY_ADDRESS = 42;    //I2C comms w/ other Arduino

//Ethernet
byte mac[]    = {  0xxx, 0xxx, 0xxx, 0xxx, 0xxx, 0xxx };
byte server[] = { xxx, xxx, xxx, xxx};
EthernetClient ethClient;
PubSubClient client(server, 1883, callback, ethClient);
unsigned long keepalivetime=0;

void callback(char* topic, byte* payload, unsigned int length) {
// handle message arrived
}

void setup()
{

    Wire.begin (MY_ADDRESS);
    Serial.begin (9600);
    Serial.println("starting");

    //wait for IP address
	while (Ethernet.begin(mac) != 1)

	{
		Serial.println("Error getting IP address via DHCP, trying again...");
		delay(10000);
	}

	//Ethernet.begin(mac, ip);
	Serial.println("ethernet OK");
	keepalivetime=millis();
	Wire.onReceive (receiveEvent);
}  // end of setup

volatile struct
{
int                   nodeID;         //node ID (1xx, 2xx, 3xx);  1xx = basement, 2xx = main floor, 3xx = outside
int            sensorID;        //sensor ID (2, 3, 4, 5)
unsigned long         var1_usl;         //uptime in ms
float                 var2_float;       //sensor data?
float            var3_float;        //battery condition?
int                   var4_int;
} SensorNode;


//***** I'm using this flag to indicate that the MQTT msg has not been sent!
//this is what is telling me that I haven't succeeded in sending MQTT message.
int sendMQTT = 0;


//**** just a flag to indicate that there's new data to print out on serial monitor.
//not very important.
volatile boolean haveData = false;


void loop()
{
	//print out data on serial monitor.
	if (haveData)
	{
	Serial.print ("Received Device ID = ");
	Serial.println (SensorNode.sensorID);
	Serial.print ("    Time = ");
	Serial.println (SensorNode.var1_usl);
	Serial.print ("    var2_float ");
	Serial.println (SensorNode.var2_float);

	sendMQTT = 1;  //flag that new data avaialble for MQTT.

	haveData = false;
	}  // end if haveData

	if (sendMQTT == 1)
	{
		if (client.connect("arduinoClient"))   //*********** BAD, RETURNS ZERO too OFTEN*************
		{
			Serial.println("starting MQTT send");

			//send var2_float
			int varnum = 2;
			char buff_topic[6];
			char buff_message[7];
			sprintf(buff_topic, "%02d%01d%01d", SensorNode.nodeID, SensorNode.sensorID, varnum);
			Serial.println(buff_topic);
			dtostrf (SensorNode.var2_float, 4, 1, buff_message);
			client.publish(buff_topic, buff_message);

			delay(200);

			//send var3_float
			varnum = 3;
			sprintf(buff_topic, "%02d%01d%01d", SensorNode.nodeID, SensorNode.sensorID, varnum);
			Serial.println(buff_topic);
			dtostrf (SensorNode.var3_float, 4, 1, buff_message);
			client.publish(buff_topic, buff_message);

			//set flag to indicate MQTT messages successfully sent
			sendMQTT = 0;
			Serial.println("finished MQTT send");
		}//end if client.connect
		else
		{
			delay(300);	//delay a bit before trying to connect again.  Not sure if this helps.
		}
	}//end if sendMQTT

	//client.loop();
	if ((millis() - keepalivetime)>10000)
	{
		client.loop();
		keepalivetime = millis();
	}

}  // end of loop

 

———————————————————————————–