Hello, I'm playing with Home Assistant to automate my house and I'm building my own MQTT sensors/switches using an Arduino Duemilanove with Ethernet shield. The board runs fine for about a couple of days but after some time the connection to the broker fails and cannot be recovered until I reset Arduino.
The broker runs in my own LAN and it's the embedded one in HA.
My code is very simple:
#include <Ethernet.h>
#include <PubSubClient.h>
const char* mqtt_server = "192.168.1.100";
const char* mqtt_username = "myuser";
const char* mqtt_password = "mypassword";
EthernetClient ethClient;
PubSubClient client;
String clientId = "test";
uint8_t mac[6] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x06};
char msg[32];
const int pinIn[4] = { 5, 6, 7, 8 };
const int pinOut[4] = { A0, A1, A2, A3 };
int oldIn[4];
void callback(char* topic, byte* payload, unsigned int length) {
if (strlen(topic) > 17) return;
if (strcmp(topic, "home/alarm/rele/1") == 0)
{
digitalWrite(pinOut[0], strncmp((char *)payload, "ON", 2));
int val = bitRead(PORTC, 0);
client.publish("home/alarm/rele/1/state", val ? "OFF" : "ON", true);
}
}
void reconnect() {
while (!client.connected())
{
Serial.print("Attempting MQTT connection...");
if (client.connect(clientId.c_str(), mqtt_username, mqtt_password))
{
Serial.println("connected");
client.subscribe("home/alarm/rele/+");
break;
}
else
{
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
}
delay(5000);
}
}
void setup() {
for (int i = 0; i < 4; i++)
{
pinMode(pinIn[i], INPUT_PULLUP);
oldIn[i] = digitalRead(pinIn[i]);
pinMode(pinOut[i], OUTPUT);
digitalWrite(pinOut[i], HIGH);
}
Serial.begin(115200);
if (Ethernet.begin(mac) == 0) {
Serial.println(F("Unable to configure Ethernet using DHCP"));
for (;;);
}
Serial.println(F("Ethernet configured via DHCP"));
Serial.print("IP address: ");
Serial.println(Ethernet.localIP());
Serial.println();
client.setClient(ethClient);
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
}
void loop() {
if (!client.connected()) reconnect();
client.loop();
for (int i = 0; i < 4; i++)
{
int val = digitalRead(pinIn[i]);
if (val != oldIn[i])
{
oldIn[i] = val;
char topic[32];
sprintf(topic, "home/alarm/sensor/%u", i+1);
client.publish(topic, val ? "ON" : "OFF", true);
}
}
}
Here a sample output:
Ethernet configured via DHCP
IP address: 192.168.1.224Attempting MQTT connection...connected
...
[after some days]
...
Attempting MQTT connection...failed, rc=-2 try again in 5 seconds
Attempting MQTT connection...failed, rc=-2 try again in 5 seconds
Attempting MQTT connection...failed, rc=-2 try again in 5 seconds
Attempting MQTT connection...failed, rc=-2 try again in 5 seconds
Attempting MQTT connection...failed, rc=-2 try again in 5 seconds
Attempting MQTT connection...failed, rc=-2 try again in 5 seconds
Attempting MQTT connection...failed, rc=-2 try again in 5 seconds
Attempting MQTT connection...failed, rc=-2 try again in 5 seconds
The value -2 is "MQTT_CONNECT_FAILED".
When this happens it won't reconnect anymore. But just resetting the Arduino leads to an immediate connection.
Given this behavior I guess the problem is on the Arduino side: do you see any evidence of mistakes in my code?