Skip to content

Pico W need too much time for receiving request data in random cases #46

@peterbay

Description

@peterbay

I have a for example a small web page with repeated ajax requests. Page is sending one request per second and server on Pico W needs different times for processing same request. In my case it varies between 40 ms and 250 ms.

I expected the time for processing the request to be approximately in the range of 40 to 80ms.

Connection to Pico is fast and when i added some debug prints to poll() function in server.py, then i found, that the bottleneck is function - self._receive_header_bytes(conn)

   def poll(self):
        try:
            conn, client_address = self._sock.accept()

            with conn:
                conn.settimeout(self._timeout)

                start_msecs = supervisor.ticks_ms()

                # Receiving data until empty line
                header_bytes = self._receive_header_bytes(conn)

                print(f"time to receive header bytes: {supervisor.ticks_ms() - start_msecs} ms")

                # Return if no data received

example of printed output (it's not the same sample as shown in image)

time to receive header bytes: 157 ms
time to receive header bytes: 1 ms
time to receive header bytes: 152 ms
time to receive header bytes: 1 ms
time to receive header bytes: 129 ms
time to receive header bytes: 1 ms
time to receive header bytes: 12 ms
time to receive header bytes: 95 ms
time to receive header bytes: 210 ms
time to receive header bytes: 1 ms
time to receive header bytes: 12 ms
time to receive header bytes: 1 ms
time to receive header bytes: 46 ms
time to receive header bytes: 1 ms
time to receive header bytes: 167 ms
time to receive header bytes: 188 ms
time to receive header bytes: 199 ms
time to receive header bytes: 208 ms

image1
image2

example code:

import os
import time
import ipaddress
import wifi
import socketpool

import microcontroller

from adafruit_httpserver.server import HTTPServer
from adafruit_httpserver.request import HTTPRequest
from adafruit_httpserver.response import HTTPResponse
from adafruit_httpserver.methods import HTTPMethod
from adafruit_httpserver.mime_type import MIMEType
from adafruit_httpserver.status import CommonHTTPStatus

#  set static IP address
ipv4 = ipaddress.IPv4Address("192.168.88.99")
netmask = ipaddress.IPv4Address("255.255.255.0")
gateway = ipaddress.IPv4Address("192.168.88.1")

wifi.radio.set_ipv4_address(ipv4=ipv4, netmask=netmask, gateway=gateway)
#  connect to your SSID
wifi.radio.connect(
    os.getenv("CIRCUITPY_WIFI_SSID"), os.getenv("CIRCUITPY_WIFI_PASSWORD")
)

print("Connected to WiFi")
pool = socketpool.SocketPool(wifi.radio)
server = HTTPServer(pool)

@server.route("/")
def base(request: HTTPRequest):  # pylint: disable=unused-argument
    with HTTPResponse(request, content_type=MIMEType.TYPE_HTML) as response:
        response.send("""
<html>
    <header>
        <script>
            const ajax = function (opt, cb) {
                const headers = opt.headers || {},
                    body = opt.body || "",
                    xhr = new XMLHttpRequest();

                xhr.open(opt.method || (body ? "POST" : "GET"), opt.url || "/", true);
                xhr.ontimeout = xhr.onabort = xhr.onerror = function (e) {
                    console.error("XHR error: ", e, "opt: ", opt);
                };
                xhr.onreadystatechange = function () {
                    if (xhr.readyState === 4) {
                        cb(xhr.status, xhr.response || xhr.responseText);
                    }
                };
                headers["Content-Type"] = headers["Content-Type"] || "application/x-www-form-urlencoded";
                for (const f in headers) {
                    xhr.setRequestHeader(f, headers[f]);
                }
                xhr.send(body);
            };

            function ajaxRequest(request, interval) {
                const ax = function () {
                    ajax(request, function (code, response) {
                        if (code == 200 && response) {
                            console.log("response", response);
                        }
                        if (interval) {
                            setTimeout(ax, interval);
                        }
                    });
                };
                ax();
            }

            data = {"id":"sw1","value":true}
            intervalMs = 1000

            ajaxRequest({ url: "/api", method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(data) }, intervalMs);

        </script>
    </header>
    <body>
        sapmle page with ajax request every 1 second
    </body>
</html>""")


@server.route("/api", HTTPMethod.POST)
def base(request: HTTPRequest):
    print("api request", request.body)
    with HTTPResponse(request, content_type=MIMEType.TYPE_JSON) as response:
        response.send('{"status": "ok"}')


print("starting server..")
# startup the server
try:
    server.start(str(wifi.radio.ipv4_address))
    print("Listening on http://%s:80" % wifi.radio.ipv4_address)
    
#  if the server fails to begin, restart the pico w
except OSError:
    time.sleep(5)
    print("restarting..")
    microcontroller.reset()

while True:
    try:
        server.poll()

    except Exception as e:
        print(e)
        continue

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions