ENOMEM when sending request

All ESP32 boards running MicroPython.
Target audience: MicroPython users with an ESP32 board.
Post Reply
jairov96
Posts: 4
Joined: Sat Aug 06, 2022 2:32 pm

ENOMEM when sending request

Post by jairov96 » Sun Aug 07, 2022 12:13 pm

Hello!

As you are most likely about to see, efficient code is not quite my thing. Coding isn't either, but I try :lol:

Running in an ESP-Wroom-32

I'm running into some issues where my code permanently returns "ENOMEM" error codes when trying to run the function sendPostRequest()

pastecode

Code: Select all

import machine
import time
from time import sleep
import ntptime
import urequests
import ujson
from machine import I2C, Pin
import BMP280
import gc


# Functions
def set_ntp_time():
    # This sets the esp32 time to be accurate using Network Time Protocol.
    ntptime.host = "1.europe.pool.ntp.org"
    ntptime.settime()
    del (ntptime.host)


def turn_on_bmp280():
    try:
        i2c = I2C(1, scl=Pin(22), sda=Pin(21), freq=10000)
        bmp = BMP280.BMP280(i2c)
        print("sensor connected")
        return (bmp)
    except Exception as e:
        print("Error: ", e)


def send_influx_measurement(
        endpoint,
        api_key,
        device_name,
        sensor_name,
        sensor_location,
        measurement):

    influx_measurement = "weather"
    timestamp = time.time_ns() + 946684800000000000  # add 30 years in ns

    headers = {}
    headers['Authorization'] = 'Token %s' % api_key

    body = "{},device={},sensor={},location={} temperature={} {}".format(
            influx_measurement,
            device_name,
            sensor_name,
            sensor_location,
            measurement,
            timestamp)
    print(body)

    sendPostRequest(endpoint, headers, body)


def sendPostRequest(url, headers, data):
    try:
        response = urequests.post(url, headers=headers, data=data)
        if response.status_code != 204:
            print("Request was not successful: ", response.status_code)
    except Exception as e:
        print("Error sending request:", e)
    del (response)


# Main
def main():
    with open('configuration.json') as rawJson:
        configuration = ujson.loads(rawJson.read())
        submit_interval = configuration.get("submit_interval")
        influx_db_endpoint = configuration.get("influx_db_endpoint")
        influx_db_api_key = configuration.get("influx_db_api_key")
        device_name = configuration.get("device_name")
        sensor_name = configuration.get("sensor_name")
        sensor_location = configuration.get("sensor_location")

    set_ntp_time()
    sensor = turn_on_bmp280()
    while sensor:
        try:
            print("\nfree mem: ", gc.mem_free())
            send_influx_measurement(
                    influx_db_endpoint,
                    influx_db_api_key,
                    device_name,
                    sensor_name,
                    sensor_location,
                    sensor.temperature)
            print("free mem after request: ", gc.mem_free())
            sleep(float(submit_interval))
        except Exception as e:
            print("Error: ", e)
            print("Memory collected by gc = ", gc.collect())
            # machine.reset()


main()

Clearly, I am doing something wrong. Because usually it takes 2 runs of the while sensor loop to run in to the enomem issue, see this log for example:

Code: Select all

Connection successful
('192.168.2.96', '255.255.255.0', '192.168.2.1', '192.168.2.20')

sensor connected
free mem:  88656
weather,device=ESP32_up2,sensor=bmp280,location=outside temperature=32.38 1659874123232696000

free mem after request:  84912


free mem:  84896
weather,device=ESP32_up2,sensor=bmp280,location=outside temperature=32.37 1659874129273187000


Error sending request: [Errno 12] ENOMEM
Collect empty memory None
free mem after request:  96016
I have the feeling that there is no space to return the response from urequests.post, but I already tried to remove the "response = [...]" assignment without success.


Any hints will be welcome!

jairov96
Posts: 4
Joined: Sat Aug 06, 2022 2:32 pm

Re: ENOMEM when sending request

Post by jairov96 » Sun Aug 07, 2022 3:32 pm

Turns out the only thing I need to do in order to fix a problem is post it in the forum.

After a bit of tinkering I figured that it's a good practice to actually close the response!

Code: Select all

def sendPostRequest(url, headers, data):
    try:
        response = urequests.post(url, headers=headers, data=data)
        if response.status_code != 204:
            print("Request was not successful: ", response.status_code)
        response.close()
    except Exception as e:
        print("Error sending request:", e)
        return
A very simple detail that at least for now It's making my code operational without reaching the limit of memory.

Post Reply