Skip to content

ESP8266 Losing packets #917

Closed
Closed
@drmpf

Description

@drmpf

I am coding a UART to WiFi bridge for ESP8266 running as a server.
Using build 1.6.5-947-g39819f0
I am finding that the ESP client is losing packets between the ESP TCP/IP stack and the client.available() method.

ESP Code is

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
// normally DEBUG is commented out
#define DEBUG
bool NoDelayFlag = true;
WiFiServer server(80);
WiFiClient client;
uint32_t timeout = 0;

void setup ( void ) {
  WiFi.mode(WIFI_STA);
  Serial.begin (9600);
  delay(10);
  Serial.println();
  for (int i = 4; i > 0; i--) {
#ifdef DEBUG
    Serial.print(i);
    Serial.print(' ');
#endif
    delay(500);
  }
#ifdef DEBUG
  Serial.println();
  Serial.println(F("Starting Setup"));
#endif
  char ssid[] = "xxxxxx"; 
  char password[] = "xxxxxx";
  char staticIP[] = "192.168.0.100";
  uint16_t portNo = 4989;
  timeout = 15000;

  server = WiFiServer(portNo);
  // Initialise wifi module
#ifdef DEBUG
  Serial.println(F("Connecting to AP"));
  Serial.print("ssid '");
  Serial.print(ssid);
  Serial.println("'");
  Serial.print("password '");
  Serial.print(password);
  Serial.println("'");
#endif
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
#ifdef DEBUG
    Serial.print(".");
#endif
  }
#ifdef DEBUG
  Serial.println();
  Serial.println(F("Connected!"));
#endif

  if (*staticIP != '\0') {
    // config static IP
    IPAddress ip(192,168,0,100);
    IPAddress gateway(192,168,0,1); // set gatway to ... 1
#ifdef DEBUG
    Serial.print(F("Setting gateway to: "));
    Serial.println(gateway);
#endif
    IPAddress subnet(255, 255, 255, 0);
    WiFi.config(ip, gateway, subnet);
  } // else leave as DHCP

  // Start listening for connections
#ifdef DEBUG
  Serial.println(F("Start Server"));
#endif
  server.begin();
  server.setNoDelay(NoDelayFlag);
#ifdef DEBUG
  Serial.println(F("Server Started"));
  // Print the IP address
  Serial.print(WiFi.localIP());
  Serial.print(':');
  Serial.println(portNo);
  Serial.println(F("Listening for connections..."));
#endif

  client = server.available();
#ifdef DEBUG
  Serial.print("+++"); // end of setup start listening now
#endif
}


static const size_t bufferSize = 128;
static uint8_t sbuf[bufferSize];
unsigned long timeoutTimerStart = 0;
const unsigned long SEND_DELAY_TIME = 10; // 10mS delay befor sending buffer

static const size_t SEND_BUFFER_SIZE = 1300; 
static uint8_t sendBuffer[SEND_BUFFER_SIZE+10];
size_t sendBufferIdx = 0;
unsigned long sendTimerStart = 0;
bool alreadyConnected = false;
// the loop routine runs over and over again forever:
void loop() {
  timeout = 45000;   //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<,  remove this later
  if (!client) { // see if a client is available
    client = server.available(); // evaluates to false if no connection
  } else {
    // have client
    if (!client.connected()) {
      if (alreadyConnected) {
        // client closed so clean up
        closeConnection();
      }
    } else {
      // have connected client
      if (!alreadyConnected) {
        client.setNoDelay(NoDelayFlag);
        alreadyConnected = true;
        sendBufferIdx = 0;
        // start timer
        timeoutTimerStart = millis();
      }
    }
  }

  //check UART for data
  if (Serial.available()) {
    size_t len = Serial.available();

    if (len > 0) { // size_t is an unsigned type so >0 is actually redundent
      sendTimerStart = millis();
      size_t will_copy = (len < (SEND_BUFFER_SIZE - sendBufferIdx)) ? len : (SEND_BUFFER_SIZE - sendBufferIdx);
      Serial.readBytes(sendBuffer + sendBufferIdx, will_copy);
      sendBufferIdx += will_copy;
      if (alreadyConnected && client) {
        if (sendBufferIdx == SEND_BUFFER_SIZE) {
          // buffer full
          client.write((const uint8_t *)sendBuffer, sendBufferIdx);
          client.flush();
          sendBufferIdx = 0;
        }
        delay(0); // yield
      }
    }
  }

  if (alreadyConnected && client) {
    if ((sendBufferIdx > 0) && ((millis() - sendTimerStart) > SEND_DELAY_TIME)) {
      client.write((const uint8_t *)sendBuffer, sendBufferIdx);
      client.flush();
      sendBufferIdx = 0;
    }
    delay(0); // yield
  }

  if (client) {
    while (client.available()) {
       timeoutTimerStart = millis();  // reset timer
      int in = client.read();
     if ((in == '{') || (in=='}')) {
       sendBuffer[sendBufferIdx++] = '*';
     } else {
       sendBuffer[sendBufferIdx++] = in;
     }      
      Serial.write(in);
      delay(0); // yield
    }
  }
  // see if we should drop the connection
  if (alreadyConnected && (timeout > 0) && ((millis() - timeoutTimerStart) > timeout)) {
    closeConnection();
  }
}

void closeConnection() {
  alreadyConnected = false;
  WiFiClient::stopAll(); // stop all clients and release memory.
  client = server.available(); // evaluates to false if no connection
}

Testing with Wireshark from Windows, I find the following
where the client sends {.} to the ESP which responds with
. from the ESP code (above) and . from the Arduino code consuming the ESP serial out. E.g.

{.}*.*_._.
{.Uno Control Application.
`1000|d~Set/Read Digital Pins|p~Plot Digital Inputs|a~Set/Read Analog Inputs|b~Plot Analog Inputs|s~Set 

AREF Analog Ref Volts|h~Help}

A longer sequence of msgs is

{.}*.*_._.
{.Uno Control Application.
`1000|d~Set/Read Digital Pins|p~Plot Digital Inputs|a~Set/Read Analog Inputs|b~Plot Analog Inputs|s~Set 

AREF Analog Ref Volts|h~Help}38.00,0.00,0.00,0.00,0.00,0.00,0.00
{.}*.*_._.
{.Uno Control Application.
`1000|d~Set/Read Digital Pins|p~Plot Digital Inputs|a~Set/Read Analog Inputs|b~Plot Analog Inputs|s~Set 

AREF Analog Ref Volts|h~Help}39.00,0,0,0,0,0,0,0,0,0,0,0
39.00,0.00,0.00,0.00,0.00,0.00,0.00
{.}*.*_._.
{.Uno Control Application.
`1000|d~Set/Read Digital Pins|p~Plot Digital Inputs|a~Set/Read Analog Inputs|b~Plot Analog Inputs|s~Set 

AREF Analog Ref Volts|h~Help}40.09,0.00,0.00,0.00,0.00,0.00,0.00
41.00,0,0,0,0,0,0,0,0,0,0,0
41.00,0.00,0.00,0.00,0.00,0.00,0.00
{.}42.00,0.00,0.00,0.00,0.00,0.00,0.00
43.00,0,0,0,0,0,0,0,0,0,0,0
43.00,0.00,0.00,0.00,0.00,0.00,0.00
44.00,0.00,0.00,0.00,0.00,0.00,0.00

however the ESP looses the last {.} above and does not respond and the client closes the connection due to lack of response.
Checking the WireShark files shows that the {.} packet was acked by the ESP, but the bytes did not make it to the client.available() call.
client sends {.}
24 3.833327000 192.168.0.2 192.168.0.100 TCP 57 59029→4989 [PSH, ACK] Seq=10 Ack=714 Win=16807 Len=3
Esp acks {.}
25 3.950966000 192.168.0.100 192.168.0.2 TCP 54 4989→59029 [ACK] Seq=714 Ack=13 Win=5828 Len=0

This problem only seems to happen when the ESP is also sending data back i.e. the
41.00,0,0,0,0,0,0,0,0,0,0,0
etc.
If I disable the sending of that extra data, things seem to work.
Data and responses are provided by an Arduino board connected to the ESP serial TXRX
EDIT: Actually also loose packet data even when not sending extra data back.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions