Skip to content

OSError: [Errno 12] ENOMEM ESP32-Micropython-Azure-Event-Hub-Client #5219

Description

@arslan437

Hi,
I'm working on a project to connect esp32 to Azure event/iot hub using gloveboxes git project.
But I'm receiving this error (OSError: [Errno 12] ENOMEM ) on the line number 113
Link to this github repository is
https://github.com/gloveboxes/ESP32-Micropython-Azure-IoT-and-Event-Hub-Client

import iothub
import eventhub
import socket
import ussl
import utime as time
import network
from machine import I2C, Pin, ADC
import ssd1306 as oled
import gc
import config
import sensor_fake

# i2c = I2C(scl=Pin(4), sda=Pin(5))
i2c = I2C(scl=Pin(22), sda=Pin(21))
builtinLedPin = 5

display = None
builtinLed = None

cfg = config.Config('config.eventhub.json')
mySensor = cfg.sensor.Sensor(i2c)


if cfg.hubType == 'eventhub':
  hub = eventhub.EventHub(cfg.host, cfg.eventHubName, cfg.eventHubPolicyName, cfg.key)
elif cfg.hubType == 'iothub':
  hub = iothub.IotHub(cfg.host, cfg.deviceId, cfg.key)

wlan = network.WLAN(network.STA_IF)

lastUpdated = 0
updateSas = True


def newSasToken():
    global lastUpdated, updateSas, SAS
    if time.ticks_diff(time.time(), lastUpdated) > 60 * 15:
        lastUpdated = time.time()
        updateSas = True

    if updateSas:
        SAS = hub.generate_sas_token()
        print('Updating Sas')
        updateSas = False


def initDisplay(i2c):
    global display, builtinLed
    i2cDevices = I2C.scan(i2c)
    if 60 in i2cDevices:
        display = oled.SSD1306_I2C(128, 64, i2c)
        return True
    else:
        builtinLed = Pin(builtinLedPin, Pin.OUT)
        return False


def wlan_connect(ssid='MYSSID', password='MYPASS'):
    if not wlan.active() or not wlan.isconnected():
        wlan.active(True)
        print('connecting to:', ssid)
        wlan.connect(ssid, password)
        while not wlan.isconnected():
            pass
    print('network config:', wlan.ifconfig())


def checkwifi():
    blinkcnt = 0
    while not wlan.isconnected():
        time.sleep_ms(500)


def main(use_stream=True):

    s = socket.socket()
    ai = socket.getaddrinfo(cfg.host, 443)
    addr = ai[0][-1]
    s.close()

    count = 0
    errorCount = 0

    while True:
        if not oledDisplay:
            builtinLed.value(0)  # turn on led

        checkwifi()
        newSasToken()
        count = count + 1

        temperature, pressure, humidity = mySensor.measure()
        light = 0
        freeMemory = gc.mem_free()

        if oledDisplay:
            display.fill(0)
            display.text('t:' + str(temperature), 0, 0)
            display.text('p:' + str(pressure), 0, 9)
            display.text('h:' + str(humidity), 0, 18)
            display.text('m:' + str(freeMemory), 0, 27)
            display.text('c:' + str(count), 0, 36)
            display.text('d:' + cfg.deviceId, 0, 45)
            display.text('e:' + str(errorCount), 0, 53)
            display.show()

        data = b'{"DeviceId":"%s","Id":%u,"Mem":%u,"Celsius":%s,"hPa":%s,"Humidity":%s, "Geo":"%s", "Light":%d, "Errors":%d}' % (
            cfg.deviceId, count, freeMemory, temperature, pressure, humidity, cfg.location, light, errorCount)

        try:
            s = socket.socket()
            s.connect(addr)
            s = ussl.wrap_socket(s)  # SSL wrap

            # Send POST request to Azure IoT Hub
            # s.write("POST /devices/" + cfg.deviceId +
            #         "/messages/events?api-version=2016-02-03 HTTP/1.0\r\n")

            s.write("POST " + hub.endpoint + " HTTP/1.1\r\n")
            # HTTP Headers
            s.write("Host: " + cfg.host + "\r\n")
            s.write("Authorization: " + SAS + "\r\n")
            s.write("Content-Type: application/json\r\n")
            s.write("Connection: close\r\n")
            s.write("Content-Length: " + str(len(data)) + "\r\n\r\n")
            # Data
            s.write(data)

            # Print 128 bytes of response
            print(s.read(128)[:12])

            s.close()
        except:
            print('Problem posting data')
            errorCount = errorCount + 1
        finally:
            if not oledDisplay:
                builtinLed.value(1)  # turn off led

            print('messages sent: %d, errors: %d' % (count, errorCount))
            time.sleep(cfg.sampleRate)


oledDisplay = initDisplay(i2c)
if oledDisplay:
    display.text("welcome", 0, 0)
    display.show()

wlan_connect(cfg.wifiSsid, cfg.wifiPwd)

time.sleep(2)  # allow for a little settle time
main()

Activity

  1. dpgeorge commented on Oct 16, 2019

    @dpgeorge
    Member

    But I'm receiving this error (OSError: [Errno 12] ENOMEM ) on the line number 113

    SSL connections take a lot of memory, and usually you can only have one open at a time.

    What is the full output of the script when it runs into an error?

    You should move the s.close() line from the end of the try: to the start of the finally:. That should help.

  2. arslan437 commented on Oct 16, 2019

    @arslan437
    Author

    It prints "Messages sent: 12, errors:12 " and numbers incrementing. At start, I didn't know what is the actual error so I commented the try, extecpt and finally, so I got this error

  3. arslan437 commented on Oct 16, 2019

    @arslan437
    Author

    this is the error that I'm receving
    image
    This is the actual code that I'm using

    # if not oledDisplay:
            #     builtinLed.value(0)  # turn on led
    
            checkwifi()
            newSasToken()
            count = count + 1
    
            #temperature, pressure, humidity = mySensor.measure()
            temperature, pressure, humidity = (36, 67, 60)
    
            light = 0
            freeMemory = gc.mem_free()
    
            # if oledDisplay:
            #     display.fill(0)
            #     display.text('t:' + str(temperature), 0, 0)
            #     display.text('p:' + str(pressure), 0, 9)
            #     display.text('h:' + str(humidity), 0, 18)
            #     display.text('m:' + str(freeMemory), 0, 27)
            #     display.text('c:' + str(count), 0, 36)
            #     display.text('d:' + cfg.deviceId, 0, 45)
            #     display.text('e:' + str(errorCount), 0, 53)
            #     display.show()
    
            data = b'{"DeviceId":"%s","Id":%u,"Mem":%u,"Celsius":%s,"hPa":%s,"Humidity":%s, "Geo":"%s", "Light":%d, "Errors":%d}' % (
                cfg.deviceId, count, freeMemory, temperature, pressure, humidity, cfg.location, light, errorCount)
    
            #try:
            s = socket.socket()
            s.connect(addr)
            s = ussl.wrap_socket(s)  # SSL wrap
    
            # Send POST request to Azure IoT Hub
            # s.write("POST /devices/" + cfg.deviceId +
            #         "/messages/events?api-version=2016-02-03 HTTP/1.0\r\n")
    
            s.write("POST /devices/" + cfg.deviceId +"/messages/events?api-version=2018-06-30 HTTP/1.0\r\n")
            #s.write("POST " + hub.endpoint + " HTTP/1.1\r\n")
            # HTTP Headers
            s.write("Host: " + cfg.host + "\r\n")
            s.write("Authorization: " + SAS + "\r\n")
            s.write("Content-Type: application/json\r\n")
            s.write("Connection: close\r\n")
            s.write("Content-Length: " + str(len(data)) + "\r\n\r\n")
            # Data
            s.write(data)
    
            # Print 128 bytes of response
            print(s.read(128)[:12])
    
            s.close()
            #except:
            print('Problem posting data')
            errorCount = errorCount + 1
            #finally:
                # if not oledDisplay:
                #     builtinLed.value(1)  # turn off led
    
            print('messages sent: %d, errors: %d' % (count, errorCount))
            time.sleep(cfg.sampleRate)
    
  4. arslan437 commented on Oct 16, 2019

    @arslan437
    Author

    I have tried your suggestion

    You should move the s.close() line from the end of the try: to the start of the finally:. That should help

    But getting the same thing

  5. DonJayamanne commented on Nov 24, 2019

    @DonJayamanne

    I'm experiencing the same issue. Getting ENOMEM at the line ussl.wrap_socket(s)
    I'm not using Azure IOT, just making a simple HTTP get, with a tiny text file (over https).
    Disappointing as everything these days is over HTTPS...

  6. enigmaniac commented on Jan 24, 2021

    @enigmaniac

    Also seeing this error intermittantly when calling ssl.wrap_socket()

  7. enesbcs commented on May 14, 2021

    @enesbcs

    Maybe its duplicated #7038 ?

  8. added a commit that references this issue on Aug 25, 2021
  9. alexwohlbruck commented on Mar 5, 2022

    @alexwohlbruck

    Is there any way to open just two simultaneous SSL connections? I want to keep one stream open indefinitely and also send some https requests intermittently without closing the original socket.

  10. jimmo commented on Jul 21, 2022

    @jimmo
    Member

    This issue is now being tracked in #8940.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions