ArduinoHA.h Code slow mqtt.loop()

Hi Everyone,

Thank for readin my post. I’m using a knock-off board with Arduino Mega R3 Wifi
this board had ESP8266 on the board. https://Arduino Mega R3 - AliExpress Link

The ESP sometimes works and other times doesn’t. when I add more HASwitches it just keep looping like below and doen’t accept commands from Home Assistant.

and when I add only one or two switches and activate the switches on=>Off=>On…
within a few clicks the ESP will drop the connection to MQTT or to the Wifi and resets. this is fursterating as I can’t figure what is wrong… is it a memory leak issue or something in the WiFiEsp or ArduinoHA libraries… I don’t know.

The below code works somehow stable when I have only two HASwitch only, when I add HASelect and change the value in Home Assistant, I get [WiFiEsp] Timeout.

The code is not cleaned and just for testing but I wanted to track where is the issue.


//////////////////////////////////////
#include <ArduinoHA.h>
#include <WiFiEsp.h>
#include "prvWifiMQTTSetup.h"  // Wifi and MQTT credentials
/////////////////////////////////////
// Digital Output
int st_Led = 13;
int Buzzer = 49;
int LED1 = 42; 
int LED2 = 43;
int LED3 = 44;
int LED4 = 45;
int LED5 = 46;
int Relay1 = 47;
int Relay2 = 48;
/////////////////////////////////////
/////////////////////////////////////
// LCD & Keypad
#include <LiquidCrystal.h>
int BackLight = 53;
int COL1 = 33; 
int COL2 = 32;
int COL3 = 31;
int COL4 = 30;
int ROW1 = 37;
int ROW2 = 36;
int ROW3 = 35;
int ROW4 = 34;

int W_MBR = A0;
int W_FR = A1;
int W_Ktcn = A2;
int W_DR = A3;
int W_GBR = A4;
int W_Str = A5;
int W_GR = A6;
int D_F = 18;
int D_B = 19;
int D_G = 20;


LiquidCrystal lcd(41, 40, 22, 23, 24, 25, 26, 27, 28, 29);
unsigned char Switch;
/////////////////////////////////////
int status = WL_IDLE_STATUS;

#define AlarmTopic "/homeassistant/HouseAlarm"      
#define AlarmTopicStatus "/homeassistant/HouseAlarm/Replies"      

#define nMin 0
#define nMax 100

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void sBuzz(unsigned int time, unsigned int count, unsigned int silent );
void reconnect();
unsigned char ScanKeys();
unsigned long lastReadAt = millis();

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void onConnected(); 
void onSwitchCommand(bool state, HASwitch* sender);
void onMessage(const char* topic, const uint8_t* payload, uint16_t length);
void onSelectCommand(int8_t index, HASelect* sender);
void onNumberCommand(HANumeric number, HANumber* sender);


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
unsigned char ScanKeys();
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

WiFiEspClient wifiClient;

/// Must Define the device then HAMqtt then the sensors and switches
HADevice device("XAlarm");
byte mac[] = {0x00, 0x10, 0xFA, 0x6E, 0x38, 0x4A};
HAMqtt mqtt(wifiClient, device);



HASwitch Switch1("Switch1");
HASwitch Switch2("Switch2");

HASelect Dropdown1("Alarm Mode");
HANumber Numeric1("myNumber", HANumber::PrecisionP1);

HABinarySensor Win_MB("Window1");
HABinarySensor Win_FR("Window2");
HABinarySensor Win_Ktc("Window3");
HABinarySensor Win_GBR("Window4");
HABinarySensor Win_DR("Window5");
HABinarySensor Win_Str("Window6");
HABinarySensor Win_GR("Window7");
HABinarySensor Door_F("Door1");
HABinarySensor Door_B("Door2");
HABinarySensor Door_G("Door3");


void setup() 
{
/////////////////////////////////////
// Digital Output
    pinMode(LED1, OUTPUT); 
    pinMode(LED2, OUTPUT);
    pinMode(LED3, OUTPUT); 
    pinMode(LED4, OUTPUT);
    pinMode(LED5, OUTPUT);
    pinMode(Relay1, OUTPUT);
    pinMode(Relay2, OUTPUT);
    pinMode(Buzzer, OUTPUT);
    pinMode(st_Led, OUTPUT);


/////////////////////////////////////
// LCD & Keypad
    lcd.begin(16, 2);   
    pinMode(BackLight, OUTPUT);
    pinMode(COL1, INPUT); 
    pinMode(COL2, INPUT); 
    pinMode(COL3, INPUT);
    pinMode(COL4, INPUT); 
    pinMode(ROW1, OUTPUT);
    pinMode(ROW2, OUTPUT);
    pinMode(ROW3, OUTPUT); 
    pinMode(ROW4, OUTPUT);
    
  
    pinMode( W_MBR, INPUT_PULLUP);
    pinMode( W_FR, INPUT_PULLUP);
    pinMode( W_Ktcn, INPUT_PULLUP);
    pinMode( W_DR, INPUT_PULLUP);
    pinMode( W_GBR, INPUT_PULLUP);
    pinMode( W_Str, INPUT_PULLUP);
    pinMode( W_GR, INPUT_PULLUP);
    pinMode( D_F, INPUT_PULLUP);
    pinMode( D_B, INPUT_PULLUP);
    pinMode( D_G, INPUT_PULLUP);

    int key = 0 ;
    lcd.home();                   
    lcd.print(" --[  Test  ]-- ");
    digitalWrite(BackLight, HIGH);

 ///////////////////////////////////// 
  // initialize serial for debugging
  Serial.begin(115200);

  // initialize serial for ESP module
  Serial3.begin(115200);

  // initialize ESP module
  WiFi.init(&Serial3);

 /////////////////////////////////////
while ( status != WL_CONNECTED) 
  {
    sBuzz(200, 1, 1);
    Serial.print("Attempting to connect to SSID: ");
    // don't continue
    Serial.println(ssid);
    lcd.clear();
    lcd.print ("Retry " + String(ssid));
    // lcd.autoscroll();
    // lcd.noAutoscroll();
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:    
    status = WiFi.begin(ssid, pass);
    if (status == 1)  lcd.clear();  lcd.print ("   Connected    "); sBuzz(200, 3,1);
    // wait 10 seconds for connection:
    Serial.print(".");
    delay(1000);    
  }
  status = WiFi.status();

 
  Serial.println("Connected to the network===>>>");
  Serial.print(status);
  Serial.println("IP Address: ");
  Serial.println(WiFi.localIP());
   /////////////////////////////////////
/////////////////////////////////////
  // set device's details (optional)
    device.setName("AlarmSystem");
    device.setSoftwareVersion("0.0.1");  
    device.setManufacturer("ZeCorp.");
    device.setModel("000-123");
/////////////////////////////////////
  // Set the Name and Icons for the sensors/switches in the Device    
    Switch1.setIcon("mdi:toggle-switch-outline");
    Switch1.setName("Siren");
    Switch1.setRetain(true); 
    Switch1.onCommand(onSwitchCommand);

    Switch2.setIcon("mdi:toggle-switch-outline");
    Switch2.setName("Switch 2");
    Switch2.setRetain(true); 
    Switch2.onCommand(onSwitchCommand);


    Dropdown1.setOptions("DisArm;Night;Arm"); // use semicolons as separator of options
    Dropdown1.onCommand(onSelectCommand);
    Dropdown1.setIcon("mdi:home"); // optional
    Dropdown1.setName("Mode"); // optional


    Numeric1.onCommand(onNumberCommand);
  // Optional configuration
    Numeric1.setIcon("mdi:home");
    Numeric1.setName("Desk Height");
    Numeric1.setMin(nMin); // can be float if precision is set via the constructor
    Numeric1.setMax(nMax); // can be float if precision is set via the constructor
    Numeric1.setStep(1); // minimum step: 0.001f
    Numeric1.setUnitOfMeasurement("cm");
        //  Numeric1.setMode(HANumber::ModeBox);
     Numeric1.setMode(HANumber::ModeSlider);
    // You can set retain flag for the HA commands
    Numeric1.setRetain(true);

// optional properties
    Win_MB.setCurrentState(digitalRead(W_MBR));
    Win_MB.setName("Windows: Bed Room");
    Win_MB.setDeviceClass("window");
    Win_MB.setIcon("mdi:window-closed-variant");
    
    Win_FR.setCurrentState(digitalRead(W_FR));
    Win_FR.setName("Windows: Family Room");
    Win_FR.setDeviceClass("window");
    Win_FR.setIcon("mdi:window-closed-variant");


    Win_Ktc.setCurrentState(digitalRead(W_Ktcn));
    Win_Ktc.setName("Windows: Kitchen");
    Win_Ktc.setDeviceClass("window");
    Win_Ktc.setIcon("mdi:window-closed-variant");

    Win_GBR.setCurrentState(digitalRead(W_GBR));
    Win_GBR.setName("Windows: Guest Bathroom");
    Win_GBR.setDeviceClass("window");
    Win_GBR.setIcon("mdi:window-closed-variant");

    Win_DR.setCurrentState(digitalRead(W_DR));
    Win_DR.setName("Windows: Dinning Room");
    Win_DR.setDeviceClass("window");
    Win_DR.setIcon("mdi:window-closed-variant");
    
    Win_Str.setCurrentState(digitalRead(W_Str));
    Win_Str.setName("Windows: Stairs");
    Win_Str.setDeviceClass("window");
    Win_Str.setIcon("mdi:window-closed-variant");

    Win_GR.setCurrentState(digitalRead(W_GR));
    Win_GR.setName("Windows: Game Room");
    Win_GR.setDeviceClass("window");
    Win_GR.setIcon("mdi:window-closed-variant");
    
    Door_F.setCurrentState(digitalRead(D_F));
    Door_F.setName("Door: Front");
    Door_F.setDeviceClass("door");
    Door_F.setIcon("mdi:door");

    Door_B.setCurrentState(digitalRead(D_B));
    Door_B.setName("Door: Back");
    Door_B.setDeviceClass("door");
    Door_B.setIcon("mdi:door");

    
    Door_G.setCurrentState(digitalRead(D_G));
    Door_G.setName("Door: Garage");
    Door_G.setDeviceClass("door");
    Door_G.setIcon("mdi:door");
    

/////////////////////////////////////
  // MQTT Setup
        sBuzz(2000,1,1);
    mqtt.begin(MQTT_SERVER, BROKER_USERNAME, BROKER_PASSWORD);

    // mqtt.setDiscoveryPrefix("homeassistant");
    // mqtt.setDataPrefix("aha");
    // mqtt.onMessage(onMessage);
    mqtt.onConnected(onConnected);
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void loop() {
    sBuzz(10,5,1);
  mqtt.loop();
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void sBuzz(unsigned int time, unsigned int count, unsigned int Sound )
{
  for (int i = 0; i < count; i++) {
    digitalWrite(st_Led, HIGH); 
    if (Sound > 0)
      {
        digitalWrite(Buzzer, HIGH);
      }
    delay(time);  
    digitalWrite(st_Led, LOW);
    digitalWrite(Buzzer, LOW);
    delay(100);  
  }}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void reconnect() 
{
    // Loop until we're reconnected
    sBuzz(3000, 3, 1);
    // while (!wifiClient.connected()) 
    // {
    //   Serial.print("Attempting MQTT connection...");
    //   // Attempt to connect
    //   if (wifiClient.connect(MQTT_SERVER, BROKER_USERNAME, BROKER_PASSWORD)) 
    //     {
    //     Serial.println("Connected to Home Assistant");
    //     // Once connected, publish an announcement...
    //     mqtt.subscribe(AlarmTopic);
    //     } 
    //   else 
    //     {
    //     Serial.print("failed, rc=");
    //     Serial.print(wifiClient.state());
    //     Serial.println(" try again in 5 seconds");
    //     // Wait 5 seconds before retrying
    //     delay(100);
    //     }
    // }
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void onSwitchCommand(bool state, HASwitch* sender)
{
    // Serial.println("MQTT command recieved.");
    if (sender == &Switch1) {
        // the switch1 has been toggled
        // state == true means ON state
        digitalWrite(Relay1, (state ? HIGH : LOW));
        Serial.println("Relay1 = " + String((state ? HIGH : LOW)));
    } else if (sender == &Switch2) {
        // the switch2 has been toggled
        // state == true means ON state
        digitalWrite(Relay2, (state ? HIGH : LOW));
        Serial.println("Relay 2 = " + String((state ? HIGH : LOW)));
        sBuzz(200, 2, 1);
    }

    sender->setState(state); // report state back to the Home Assistant
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void onMessage(const char* topic, const uint8_t* payload, uint16_t length) 
{
  // float output;
  // char buffer[32];

  //   Serial.println("MQTT message recieved on topic: ");
  //   Serial.println(topic);
  //   Serial.print("Data: ");
  //   Serial.println((const char*)payload);
    // checkmessage(payload);
  // callback (topic, payload, length);

}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void onSelectCommand(int8_t index, HASelect* sender)
{
    Serial.println("onSelectCommand");
    switch (index) 
    {
    case 0:
        // Option "Low" was selected
        // digitalWrite(Relay1, HIGH);
        // Serial.println("onSelectCommand = case 0");

        break;

    case 1:
        // Option "Medium" was selected
        // digitalWrite(Relay1, LOW);
        // Serial.println("onSelectCommand = case 1");

        break;
    case 2:
        // Option "High" was selected
        // digitalWrite(Relay2, HIGH);
        // Serial.println("onSelectCommand = case 2");
        break;
    case 3:
        // digitalWrite(Relay2, LOW);
        // Serial.println("onSelectCommand = case 3");

    default:
        Serial.println("onSelectCommand = default");

        // unknown option
        return;
    }
    sender->setState(index); // report the selected option back to the HA panel
    if (sender->getCurrentOption()) {
        Serial.print("Current option: ");
        Serial.println(sender->getCurrentOption());
    }
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void onConnected() 
{
  Serial.println("MQTT connection established.");
  mqtt.subscribe(AlarmTopic);
  mqtt.publish(AlarmTopicStatus, "Connected");

  // Switch1.setAvailability(true);
  // Switch2.setAvailability(true);
  sBuzz(50,3,1);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void onNumberCommand(HANumeric number, HANumber* sender)
{
    if (!number.isSet()) {
        // the reset command was send by Home Assistant
        number.setBaseValue(50);
    } else {
        // you can do whatever you want with the number as follows:
        int8_t numberInt8 = number.toInt8();
        int16_t numberInt16 = number.toInt16();
        int32_t numberInt32 = number.toInt32();
        uint8_t numberUInt8 = number.toUInt8();
        uint16_t numberUInt16 = number.toUInt16();
        uint32_t numberUInt32 = number.toUInt32();
        float numberFloat = number.toFloat();
         Serial.println("Number Selected=" + String(numberInt16));
         if (numberInt16 >=200){digitalWrite(LED1, HIGH);}
         if (numberInt16 >=350){digitalWrite(LED2, HIGH);}
         if (numberInt16 >=450){digitalWrite(LED3, HIGH);}
         if (numberInt16 >=600){digitalWrite(LED4, HIGH);}
         if (numberInt16 >=900){digitalWrite(LED5, HIGH);}
         
         if (numberInt16 < 200){digitalWrite(LED1, LOW);}
         if (numberInt16 <350){digitalWrite(LED2, LOW);}
         if (numberInt16 <450){digitalWrite(LED3, LOW);}
         if (numberInt16 <600){digitalWrite(LED4, LOW);}
         if (numberInt16 <900){digitalWrite(LED5, LOW);}
    }
   
    sender->setState(number); // report the selected option back to the HA panel
}

This is what is I’m receiving on the Serial port

[WiFiEsp] Initializing ESP module
[WiFiEsp] Initilization successful - 1.5.4
Attempting to connect to SSID: MySSID
[WiFiEsp] Connected to MySSID
.Connected to the network===>>>
1IP Address:
192.168.68.22
[WiFiEsp] Connecting to 192.168.68.88
MQTT connection established.
[WiFiEsp] Disconnecting  3
[WiFiEsp] Connecting to 192.168.68.88
MQTT connection established.
[WiFiEsp] Disconnecting  3
[WiFiEsp] Connecting to 192.168.68.88
MQTT connection established.
[WiFiEsp] Disconnecting  3
[WiFiEsp] Connecting to 192.168.68.88
MQTT connection established.
[WiFiEsp] Disconnecting  3
[WiFiEsp] Connecting to 192.168.68.88
MQTT connection established.
[WiFiEsp] >>> TIMEOUT >>>
[WiFiEsp] Data packet send error (2)
[WiFiEsp] Failed to write to socket 3
[WiFiEsp] Disconnecting  3

Are you planning to relate this to Home Assistant at all?
My suggestion would be to try it with espHome.

Hi , thank you for replying. I’m just testing this board and seeing if I can replace my house alarm with it and just wanted to understand what is going on with the ESP8266 and why it is behaving like this… I didn’t write C++/C code for 15 years and I’m not sure if I’m missing something.

1 Like