EthernetENC icon indicating copy to clipboard operation
EthernetENC copied to clipboard

Problems with first sends using EthernetENC

Open gimenezfrg opened this issue 3 years ago • 6 comments

Good evening, can anyone help me?

I'm using this LIB in a project where I have some buttons connected to the arduino and whenever someone presses a button I consump an API to inform the pressed button, it works fine, but I'm facing a strange problem, below is an example code:

#include <Arduino.h>
#include <EthernetENC.h>

EthernetClient clientLAN;
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 0, 103);

void setup()
{  
  Serial.begin(115200);

  Serial.println("Tentando conectar via ETHERNET...");

  if (Ethernet.begin(mac) == 0)
  {
      Serial.println("Falha ao configurar a ETHERNET usando DHCP");  
  }
  else
  { 
      if (Ethernet.hardwareStatus() == EthernetNoHardware) {
        Serial.println("Ethernet shield was not found.");
      }
      else if (Ethernet.hardwareStatus() == EthernetW5100) {
        Serial.println("W5100 Ethernet controller detected.");
      }
      else if (Ethernet.hardwareStatus() == EthernetW5200) {
        Serial.println("W5200 Ethernet controller detected.");
      }
      else if (Ethernet.hardwareStatus() == EthernetW5500) {
        Serial.println("W5500 Ethernet controller detected.");
      }
      else
      {
        Serial.print("Ethernet controller detected: ");
        Serial.println(Ethernet.hardwareStatus());
      }

      Serial.println("Conexão ETHERNET realizada com sucesso!");
     
      Serial.print(" IP: ");
      Serial.println(Ethernet.localIP());

      Serial.print("MSK: ");
      Serial.println(Ethernet.subnetMask());

      Serial.print(" GW: ");
      Serial.println(Ethernet.gatewayIP());

      Serial.print("DNS: ");
      Serial.println(Ethernet.dnsServerIP());
  }
  
  delay(500);
}

void loop()
{
    Serial.println("Abrindo conexão com o servidor (Via ETHERNET).");
    
    //clientLAN.clearWriteError();
    //clientLAN.setTimeout(10000);

    int clientLanStatus = clientLAN.connect(ip, 8083);
    Serial.print("Client CONNECT result:");
    Serial.println(clientLanStatus);

    if (clientLanStatus == 1)
    {
        Serial.println("Conectado ao servidor (Via ETHERNET).");
        Serial.println("Enviado dados para o servidor (Via ETHERNET).");
        
        clientLAN.println("GET /_Testes/api_teste.php?botao=B01&ligado=1&bancoDados=999&hash=ABCXYZ HTTP/1.1");
        clientLAN.println("Host: 192.168.0.103:8083");
        clientLAN.println("Connection: close");
        clientLAN.println();   

        //--.       
        
        while(clientLAN.connected()) {
          while(clientLAN.available()) {
            Serial.write(clientLAN.read());
          }
        }               

        clientLAN.flush();
        clientLAN.stop();      
        
        Serial.println();
        Serial.println("Envio finalizado.");
        Serial.println();

        delay(200);
    
    }
    else
    {         
        Serial.println("NÃO FOI POSSíVEL ENVIAR O COMANDO AO SERVIDOR!!!");  
              
        if (Ethernet.linkStatus() == 2) 
        {
          Serial.println("NÃO conectado ao servidor!!!");  
          Serial.println("Tentando reconectar...");   

          if (Ethernet.begin(mac) == 0)
          {
            Serial.println("Falha ao re-configurar a ETHERNET usando DHCP!!!");
          }
          else
          {
            Serial.println("Re-Conexão ETHERNET realizada com sucesso!");
          }
        }

        delay(500);
    }
  
    delay(2000);
}

It turns out that when connecting the arduino for the first time everything works normally, if I restart the arduino the first uploads give an error (randomly it can happen from the first to the sixth upload does not work), after that it stabilizes and all uploads work normally. I couldn't find the logic behind it.

Apparently if I comment out "clientLAN.stop();", "clientLAN.read()" and the API doesn't return anything, it doesn't. The API only returns the processing date.

Analyzing the LIB EthernetClient.ccp I arrived at this function:

int
UIPClient::connect(IPAddress ip, uint16_t port)
{
  stop();
  uip_ipaddr_t ipaddr;
  uip_ip_addr(ipaddr, ip);
  struct uip_conn* conn = uip_connect(&ipaddr, htons(port));
  if (conn)
    {
#if UIP_CONNECT_TIMEOUT > 0
      uint32_t timeout = millis() + 1000 * UIP_CONNECT_TIMEOUT;
#endif
      while((conn->tcpstateflags & UIP_TS_MASK) != UIP_CLOSED)
        {
          UIPEthernetClass::tick();
          if ((conn->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED)
            {
              data = (uip_userdata_t*) conn->appstate;
#ifdef UIPETHERNET_DEBUG_CLIENT
              Serial.print(F("connected, state: "));
              Serial.print(data->state);
              Serial.print(F(", first packet in: "));
              Serial.println(data->packets_in[0]);
#endif
              return 1;
            }
#if UIP_CONNECT_TIMEOUT > 0
          if (((int32_t)(millis() - timeout)) > 0)
            {
              conn->tcpstateflags = UIP_CLOSED;
              break;
            }
#endif
        }
    }
  return 0;
}

As I understand it, in the first submissions it does not enter this IF:

if ((conn->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED)

I've tried to increase the TimeOut (clientLAN.setTimeout(10000);) of the connection, but without success.

Does anyone have any idea what it could be?

I use EthernetENC version 2.0.2.

Evidence:

image

gimenezfrg avatar Apr 05 '22 02:04 gimenezfrg

for longer connect timeout set UIP_CONNECT_TIMEOUT in utility/uipethernet-conf.h

you can turn on debugging by uncommenting #define UIPETHERNET_DEBUG_CLIENT in Ethernet.h

JAndrassy avatar Apr 05 '22 18:04 JAndrassy

I arrived at this result with #define UIPETHERNET_DEBUG_CLIENT:

image

gimenezfrg avatar Apr 06 '22 01:04 gimenezfrg

I try to reproduce the problem. I think I am seeing it too, but I thought it is only a slow initialization. I use static IP. But your case shows that DHCP/UDP already works while TCP doesn't.

JAndrassy avatar Apr 06 '22 05:04 JAndrassy

Hello.

So, it doesn't seem just a matter of time, even waiting a while after Ethernet.begin(mac), the problem happens.

If it is the first use of the day or after a long time with the device disconnected the problem does not happen.

It only happens if in the sequence the device is turned off and on or restarted, I have the impression that there is some "dirt" from the previous connection.

gimenezfrg avatar Apr 06 '22 12:04 gimenezfrg

it couldn't replicate your problem. the client always connects.

is the MAC address and IP address you unique?

JAndrassy avatar Apr 18 '22 17:04 JAndrassy

Yes

gimenezfrg avatar Apr 18 '22 19:04 gimenezfrg