ESP8266 Developer Zone The Official ESP8266 Forum 2021-11-07T03:37:56+08:00 https://bbs.espressif.com:443/feed.php?f=7&t=75244 2021-11-07T03:37:56+08:00 2021-11-07T03:37:56+08:00 https://bbs.espressif.com:443/viewtopic.php?t=75244&p=100339#p100339 <![CDATA[Re: Web Server - Can't connect more than five times (SOLVED)]]>
I was wondering why no one had any suggestions. Especially since I broached this problem two years ago in https://bbs.espressif.com/viewtopic.php?f=7&t=51435. I felt certain that if the espconn_regist_disconcb() callback wasn't getting fired there would be a lot more people besides me complaining. This was my first clue... that it had something to do with the Arduino IDE libraries.

Well... I took the last couple of days to research the Internet about doing native development on Windows. The last time I looked one had to use a Linux VM and there was just too much learning curve and too many ways for it to go sideways on me. This time I found PlatformIO and having used Visual Studio for twenty-five+ years, I felt at home and the tutorials got me up and running promptly. I converted the code above to a Native C version and it worked first time!!!

So there is something amiss when trying to do a Native SDK under the Arduino IDE.

Statistics: Posted by Inquisitor — Sun Nov 07, 2021 3:37 am


]]>
2021-11-04T22:23:10+08:00 2021-11-04T22:23:10+08:00 https://bbs.espressif.com:443/viewtopic.php?t=75244&p=100332#p100332 <![CDATA[More information...]]>
  1. I notice that the espconn_regist_disconcb() callback NEVER gets called.
  2. I tried older development versions of the SDK
    1. Espressif SDK version 1.5.3(aec24ac9) Worked! - It continually re-serves the same page well into the thousands without issue and without memory leaks. This was downloaded in Arduino ESP8266 library 2.3.0.
    2. Subsequent versions do not work.
    3. Espressif SDK version 2.2.2-dev(38a443e) does not work after serving the file five times. - This was downloaded in the latest Arduino ESP8266 library 3.0.2.

Code:

extern "C"
{
  #include "user_interface.h"
  #include "espconn.h"
}

#define SSID "InqMakers-Guest"
#define PW "Inquisitive"
#define HOST "wp"

const char* PAGE = "<!DOCTYPE html><html><head><title>Native Server Test</title> <meta name='viewport' content='width=device-width, initial-scale=1'><script>window.addEventListener('load',()=>{ setTimeout(()=>{location.reload();},500);},false);</script></head><body>  <h1>Welcome to my Native Server Test</h1></body></html>";

void setup()
{
   Serial.begin(115200);
   while(!Serial) { Serial.print("."); delay(100); }
   delay(2000);
   
    // This is just cook-book Station connection stuff.
    Serial.printf("\n\nSDK version: %s\n", system_get_sdk_version());

    setupWiFi();
   
    // Setup and start web server listener
    static espconn listen;
    os_memset(&listen, 0, sizeof(espconn));
    listen.type = ESPCONN_TCP;
    listen.state = ESPCONN_NONE;   
    listen.proto.tcp = new esp_tcp();   
    listen.proto.tcp->local_port = 80;
   
    espconn_regist_connectcb(&listen, onConnection); 
    // This appears to be an error handler.  Haven't seen it hit yet.
    espconn_regist_reconcb(&listen, onError);
       
    printIfErr(espconn_accept(&listen), "listen");
   
   Serial.println("Ready");
}

espconn* dis = NULL;
u32 last;
u32 cnt = 0;

void loop()
{
    // The only thing we do in the loop is do the final disconnect since
    // we can't do it in the onSent() callback.
    if (dis)
    {
        u32 now = micros();
        Serial.printf("dis=%uus ", now - last);
        last = now;
       
        s8 rtn;
        if ((rtn = espconn_disconnect(dis)))
        {
            Serial.printf("ERR - disconnect = %d\n", rtn);
            if ((rtn = espconn_abort(dis)))
                Serial.printf("ERR - abort = %d\n", rtn);
        }
        if ((rtn = espconn_delete(dis)))
            Serial.printf("del=%d ", rtn);
        dis = NULL;
    }
}

void onConnection(void* c)
{
    espconn* conn = reinterpret_cast<espconn*>(c);
       
    // Incoming connection
    last = micros();
    Serial.printf("\nconn(%u), ", cnt++);   
    espconn_regist_recvcb(conn, onReceive);
    espconn_regist_sentcb(conn, onSent);
    espconn_regist_disconcb(conn, onDisconnect);   

    espconn_set_opt(conn, ESPCONN_REUSEADDR | ESPCONN_NODELAY);
    // We'll use our own buffer instead of their 2920 buffer
    //espconn_clear_opt(conn, ESPCONN_COPY | ESPCONN_KEEPALIVE);
}

void onError(void* conn, s8 err)
{
    Serial.printf("ERR=%d\n", err);
}

void onReceive(void* c, char* buf, u16 length)
{
    espconn* conn = reinterpret_cast<espconn*>(c);

    u32 now = micros();
    Serial.printf("rcv=%uus ", now - last);
    last = now;
   
    static char buffer[1024];

    // Print out the request just to make sure its what we think it is.
    memcpy(buffer, buf, length);
    *(buffer + length) = 0;
    // Serial.print(buffer);
   
    // We'll send back a page that keeps reloading,
    // so we can check for errors and/or memory leaks.
    sprintf(buffer, "HTTP/1.1 200 OK\r\n"
        "Server: InqPortal/5.0\r\n"
        "Content-Length: %d\r\n"
        "Content-type: text/html\r\n"
        "Pragma: no-cache\r\n\r\n%s", strlen(PAGE), PAGE);
    printIfErr(espconn_sent(conn, (u8*)buffer, strlen(buffer)), "send");
   
    now = micros();
    Serial.printf("snd=%uus ", now - last);
    last = now;
}

void onSent(void* c)
{
    espconn* conn = reinterpret_cast<espconn*>(c);
   
    u32 now = micros();
    Serial.printf("snt=%uus ", now - last);
    last = now;
    // Manual says we can't call disconnect in callback.  We'll use
    // cheap way of just letting the loop() do it.
    dis = conn;
}

void onDisconnect(void* c)
{
    u32 now = micros();
    Serial.printf("dis(%p)=%uus mem=%u",
        c, now - last, system_get_free_heap_size());
    last = now;   
}

void printIfErr(s8 esp, const char* msg)
{
    if (esp)
        Serial.printf("ERR - %s = %d\n", msg, esp);
}

void setupWiFi()
{
    Serial.print("\nConnecting to your router");

    wifi_set_opmode(STATION_MODE);
   
    station_config sc;
    os_memset(&sc, 0, sizeof(station_config));
    sc.bssid_set = 0;
    os_memcpy(&sc.ssid, SSID, 32);
    os_memcpy(&sc.password, PW, 64);   
    wifi_station_set_config_current(&sc);

    wifi_station_set_hostname(HOST);

    wifi_station_connect();
    while (wifi_station_get_connect_status() != STATION_GOT_IP)
    {
        Serial.print(".");
        delay(1000);
    }
    ip_info   info;
    wifi_get_ip_info(STATION_IF, &info);
    Serial.printf("\nBrowse to (http://%s/index.html) or (http://" IPSTR
        "/index.html)\n",
        HOST, IP2STR(&(info.ip)));
}

Statistics: Posted by Inquisitor — Thu Nov 04, 2021 10:23 pm


]]>
2021-11-01T22:12:44+08:00 2021-11-01T22:12:44+08:00 https://bbs.espressif.com:443/viewtopic.php?t=75244&p=100327#p100327 <![CDATA[Web Server - Can't connect more than five times]]>

  1. receiving the request
  2. responding with a simple 404
  3. see the browser display the 404
  4. waiting for the espconn_sent_callback()
  5. doing a espconn_disconnect() outside of the callback,
  6. doing a espconn_delete()
This all works fine the first 5 requests... but none after. Doing an lwIP version web server, there are methods to tell the low level that to hold/send more connections... tcp_backlog_delayed() / tcp_backlog_accepted(). There doesn't seem to be an equivalent in the native methods. Here is a rudimentary, single request at a time, test web server that illustrates the problem. It's written for the Arduino IDE, but is easily ported the other way if needed.

Code:

#include <user_interface.h>
#include <espconn.h>

#define SSID "InqMakers-Guest"
#define PW "Inquisitive"
#define HOST "wp"

void setup()
{
   Serial.begin(115200);
   while(!Serial) { Serial.print("."); delay(100); }
   delay(2000);
   
    // This is just cook-book Station connection stuff.
    setupWiFi();
   
    // Setup and start web server listener
    static espconn listen;
    os_memset(&listen, 0, sizeof(espconn));
    listen.type = ESPCONN_TCP;
    listen.state = ESPCONN_NONE;   
    listen.proto.tcp = new esp_tcp();   
    listen.proto.tcp->local_port = 80;
   
    espconn_regist_connectcb(&listen, onConnection); 
    // This appears to be an error handler.  Haven't seen it hit yet.
    espconn_regist_reconcb(&listen, onError);
       
    printIfErr(espconn_accept(&listen), "listen");
   
   Serial.println("Ready");
}

espconn* dis = NULL;
u32 last;

void loop()
{
    // The only thing we do in the loop is do the final disconnect since
    // we can't do it in the onSent() callback.
    if (dis)
    {
        u32 now = micros();
        Serial.printf("disconnect = %u us\n", now - last);
        last = now;
       
        s8 rtn;
        if ((rtn = espconn_disconnect(dis)))
        {
            Serial.printf("ERR - disconnect = %d\n", rtn);
            if ((rtn = espconn_abort(dis)))
                Serial.printf("ERR - abort = %d\n", rtn);
        }
        if ((rtn = espconn_delete(dis)))
            Serial.printf("ERR - delete = %d\n", rtn);
        dis = NULL;
    }
}

void onConnection(void* c)
{
    espconn* conn = reinterpret_cast<espconn*>(c);
       
    // Incoming connection
    last = micros();
    Serial.printf("\nonConnection\n");   
    espconn_regist_recvcb(conn, onReceive);
    espconn_regist_sentcb(conn, onSent);
    espconn_regist_disconcb(conn, onDisconnect);   

    espconn_set_opt(conn, ESPCONN_REUSEADDR | ESPCONN_NODELAY);
    // We'll use our own buffer instead of their 2920 buffer
    espconn_clear_opt(conn, ESPCONN_COPY);
}

void onError(void* conn, s8 err)
{
    Serial.printf("ERR=%d\n", err);
}

void onReceive(void* c, char* buf, u16 length)
{
    espconn* conn = reinterpret_cast<espconn*>(c);

    u32 now = micros();
    Serial.printf("onReceive = %u us\n", now - last);
    last = now;
   
    static char buffer[536];

    // Print out the request just to make sure its what we think it is.
    memcpy(buffer, buf, length);
    *(buffer + length) = 0;
    // Serial.print(buffer);
   
    // We don't care what's in there since we'll send back a 404 anyway.
    sprintf(buffer, "HTTP/1.1 404 Not Found\r\nServer: InqPortal/5.0\r\n",
        "Content-type: text/html\r\nPragma: no-cache\r\n\r\n");

    printIfErr(espconn_send(conn, (u8*)buffer, strlen(buffer)), "send");
   
    now = micros();
    Serial.printf("sent = %u us\n", now - last);
    last = now;
}

void onSent(void* c)
{
    u32 now = micros();
    Serial.printf("onSent = %u us\n", now - last);
    last = now;
    // Manual says we can't call disconnect in callback.  We'll use
    // cheap way of just letting the loop() do it.
    dis = reinterpret_cast<espconn*>(c);
;
}

void onDisconnect(void* c)
{
    Serial.printf("onDisconnect \n");
}

void printIfErr(s8 esp, const char* msg)
{
    if (esp)
        Serial.printf("ERR - %s = %d\n", msg, esp);
}

void setupWiFi()
{
    Serial.print("Connecting to your router");

    wifi_set_opmode(STATION_MODE);
   
    station_config sc;
    os_memset(&sc, 0, sizeof(station_config));
    sc.bssid_set = 0;
    os_memcpy(&sc.ssid, SSID, 32);
    os_memcpy(&sc.password, PW, 64);   
    wifi_station_set_config_current(&sc);

    wifi_station_set_hostname(HOST);

    wifi_station_connect();
    while (wifi_station_get_connect_status() != STATION_GOT_IP)
    {
        Serial.print(".");
        delay(1000);
    }
    ip_info   info;
    wifi_get_ip_info(STATION_IF, &info);
    Serial.printf("\nBrowse to (http://%s/index.html) or (http://" IPSTR
        "/index.html)\n",
        HOST, IP2STR(&(info.ip)));
}

Statistics: Posted by Inquisitor — Mon Nov 01, 2021 10:12 pm


]]>