Description
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.