Making an API Request inside a while loop causes the board to RESET.

All ESP8266 boards running MicroPython.
Official boards are the Adafruit Huzzah and Feather boards.
Target audience: MicroPython users with an ESP8266 board.
Post Reply
jamster
Posts: 2
Joined: Sun Oct 20, 2019 2:21 pm

Making an API Request inside a while loop causes the board to RESET.

Post by jamster » Sun Oct 20, 2019 2:46 pm

Hi everyone. I've been banging my head over this for a while and could use some guidance. I have an application running my Feather Huzzah which (1) Is listening for incoming HTTP requests in a while loop and (2) executing an API request to Google's Geo-location API when it receives a specific HTTP request and (3) polling other components like an ADC.

Logically it's fine. The separate components work as intended. I can receive and parse HTTP requests over the TCP socket I have open and I can communicate with the Google API, no problem. The issue is when I try to do both.

Side note: The socket is set to timeout after 300 ms, so it doesn't block permanently waiting for a connection. That would cause a problem being able to poll other components like the ADC.

Code: Select all

    # s is an IPv4 TCP socket
    s.settimeout(0.3)
    while True:
        # Wait for an incoming HTTP request on Port 80
        connection_received = True
        addr = None
        conn = None
        try:
            conn, addr = s.accept()
        except OSError:
            connection_received = False

        request_valid = True
        if connection_received:
            # Read the data from the socket (HTTP Request text)
            print('Received a connection from %s' % str(addr))
            try:
                request = conn.recv(1024)
            except OSError:
                request_valid = False
                conn.close()

            if request_valid:
                # Make an API request if the incoming HTTP request was valid
                request = str(request)
                print('Content = %s' % request)
                params = get_query_string_params(request)
                update_state(params) # Makes a call to the Google Geo Location API
                
      # Other code here to poll ADC for unrelated functionality
When it reaches the following code in the update_state() function, the board resets. Specifically, where I make an HTTP POST request with the `urequests` library.

Code: Select all

    url = "https://www.googleapis.com/geolocation/v1/geolocate?key=MY_API_KEY"
    payload = {"content type": "applications/jsonrequests", "content length": "0"}
    print('Making Location API Request ...')
    r = urequests.post(url, json=payload, ) # Reset occurs here
    text = r.text
    # Response is parsed below here
While connected with putty, I see the following in the terminal output:

Code: Select all

Making Location API Request ...

 ets Jan  8 2013,rst cause:2, boot mode:(3,7)

load 0x40100000, len 31024, room 16
tail 0
chksum 0xb4
load 0x3ffe8000, len 1104, room 8
tail 8
chksum 0x74
load 0x3ffe8450, len 824, room 0
tail 8
chksum 0x45
csum 0x45
I haven't found much on this error so far, but from what little I've been able to piece together from searching, it seems there is a problem with executing a long-running action (in this case an HTTP POST request) while I'm also running inside a `while` loop. Is that really the case? Is it a memory issue? I tried replacing the POST request with a sleep for 2 seconds, but that seems to work fine, so I don't think the request taking too long is the real problem.

DragonFire
Posts: 8
Joined: Thu Sep 10, 2020 11:15 pm

Re: Making an API Request inside a while loop causes the board to RESET.

Post by DragonFire » Thu Sep 10, 2020 11:19 pm

Hi,

Did you ever resolve this? ๐Ÿ™๐Ÿผ๐Ÿ™๐Ÿผ๐Ÿ™๐Ÿผ

This sounds almost EXACTLY like the problem I am having! I know it's not my code, since I've had an earlier version of this running without issues. But, like you said, this time I am calling the function from inside an event processing loop.

jamster
Posts: 2
Joined: Sun Oct 20, 2019 2:21 pm

Re: Making an API Request inside a while loop causes the board to RESET.

Post by jamster » Sat Sep 26, 2020 2:22 pm

DragonFire wrote: โ†‘
Thu Sep 10, 2020 11:19 pm
Did you ever resolve this?
Hey, there. Sorry for the late reply. As you can see I posted this question almost a year ago, while I was taking an IoT class in college.

To answer your question: Yes I'm sure I resolved this, but exactly what I did I don't remember at this point since it was so long ago. I said that each of the components worked, but that when I put them together I was having an issue. If I recall correctly I think it was because I had too much code in that one file (the memory on the Feather HUZZAH is very limited). My guess was that it ran out of memory while executing and forced itself to restart as a result.

To solve that problem, I had to shrink the size of the main python file as much as possible by doing stuff like:
  • Removing comments
  • Removing unnecessary variables
  • Replacing constants with literal values where they were used
  • Shrinking multi-line expressions to one-liners
  • Basically everything they teach you NOT to do in programming because it makes reading code more difficult
Once I "cut the fat" from all this code, it started working properly. There was no logical problem in the code, it was a hardware limitation of the board, as far as I know.

Anyway, in case it would still be helpful, I posted my school code on Github (I think it was Lab 6): https://github.com/jamilnyc/feather
Maybe you'll find something useful there. Good luck!

DragonFire
Posts: 8
Joined: Thu Sep 10, 2020 11:15 pm

Re: Making an API Request inside a while loop causes the board to RESET.

Post by DragonFire » Sun Sep 27, 2020 12:53 am

Thanks for the response. Timing is everything! I just figured out (this very afternoon) what is going on on my board. No solution yet, but it turns out that using the Timer class somehow causes network requests to restart the board. I am still hunting down the exact cause (with the developers help ;-) and I will came back around here and post the resolution when I find one. I already know that using the virtual timers is NOT a solution. I might need to lock the section of code that is performing the network operations. ๐Ÿคท๐Ÿฝโ€โ™‚๏ธ

BTW, I did look at the memory usage, the ESP8266 has about 35K of RAM and I have about 14.5K still free before I make the request.

Code: Select all

import gc
print("Free RAM: {0}".format(gc.mem_free()))

Post Reply