OSError: [Errno 11] EAGAIN problems



  • Sometimes I'm having this error, "OSError: [Errno 11] EAGAIN", as I see in other posts, this error is raised if send_lorawan returns zero, which can happen for two reasons, the message was added to the queue (which is what I believe you are refering to with the duty cycle limiting) or there was a LORA_STATUS_ERROR. (Post)

    In my case I think I'm having the same problem, isn't a lora status error. But the problem is that I don't understand why is happening this error, what this error is. Problems with the channel? With the socket? Payload big?

    What means the message was added to the queue? I solve it trying to send it again? I need to wait something?

    I'm not trying to patch it using try - except I want to understand if I'm doing something wrong with my data, sending, connection...

    Thank you very much!


  • Global Moderator

    Hi,
    I compiled a firmware for you to use on a Lopy4 (here) to check the EAGAIN error cause.
    For a case without error, it will output the following:

    Pycom MicroPython 1.20.2.r4 [v1.20.1.r2-357-g6153b01d3-dirty] on 2021-01-18; LoPy4 with ESP32
    Type "help()" for more information.
    >>> Running selected lines
    
    >>> 
    >>> 
    Not yet joined...
    Not yet joined...
    Not yet joined...
    Joined
    b''
    [TASK_LoRa] CMD TX
    [LoRaMAC] returning status 0
    >
    Pycom MicroPython 1.20.2.r4 [v1.20.1.r2-357-g6153b01d3-dirty] on 2021-01-18; LoPy4 with ESP32
    Type "help()" for more information.
    >>> 
    

    You should be able to use the script you already wrote, but if you want to use the example I used:

    from network import LoRa
    import socket
    import time
    import ubinascii
    
    # Initialise LoRa in LORAWAN mode.
    # Please pick the region that matches where you are using the device:
    # Asia = LoRa.AS923
    # Australia = LoRa.AU915
    # Europe = LoRa.EU868
    # United States = LoRa.US915
    lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868)
    
    # create an OTAA authentication parameters, change them to the provided credentials
    app_eui = ubinascii.unhexlify('')
    app_key = ubinascii.unhexlify('')
    #uncomment to use LoRaWAN application provided dev_eui
    dev_eui = ubinascii.unhexlify('')
    # join a network using OTAA (Over the Air Activation)
    #uncomment below to use LoRaWAN application provided dev_eui
    #lora.join(activation=LoRa.OTAA, auth=(app_eui, app_key), timeout=0)
    lora.join(activation=LoRa.OTAA, auth=(dev_eui, app_eui, app_key), timeout=0)
    
    # wait until the module has joined the network
    while not lora.has_joined():
        time.sleep(2.5)
        print('Not yet joined...')
    
    print('Joined')
    # create a LoRa socket
    s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)
    
    # set the LoRaWAN data rate
    s.setsockopt(socket.SOL_LORA, socket.SO_DR, 5)
    
    # make the socket blocking
    # (waits for the data to be sent and for the 2 receive windows to expire)
    s.setblocking(False)
    
    # send some data
    s.send(bytes([0x01, 0x02, 0x03]))
    # make the socket non-blocking
    # (because if there's no data received it will block forever...)
    s.setblocking(False)
    
    # get any data received (if any...)
    data = s.recv(64)
    print(data)
    


  • @M-m How often is that code called? What's the size of the payload? What LoRa region are you using? Are you using raw LoRa or LoRaWAN?



  • @jcaron , @Gijs I attach the things that I understand are rellevants, if you need more just tell me :)

    What I'm doing is obtaining periodically some values (float) from a datalogger and save it in a json file.

    At one point, I want to send just the last measurement (discarding and deleting all previous ones). Thus, in this moment I convert the final float values to bytes (using ustruct).

            
            with open('results.json', 'r') as f:
                data = ujson.load(f)
    
            # If we have data
            if len(data['data'])>0:
                values = data['data'][-1]
                # Obtain the one and delete the other
                data['data'] = [values]
                with open("results.json", "w") as f:
                    f.write(ujson.dumps(data)
                # Values to bytes
                payload = b''
                for i in values:
                    if i == '0':
                        val = ustruct.pack('B', 0)
                    else:
                        val = ustruct.pack('f', float(i))
                    payload = payload + val
                # Send data
                config.xarxa.LoRa_send(payload)
    

    The LoRa_send function is just one line

        def LoRa_send(self, payload):
            self.lora_socket.send(payload)
    

    Is just here when the error SOMETIMES appears,

    Unhandled exception in callback handler
    File "/flash/lib/LoRa_config.py", line 101, in LoRa_send OSError: [Errno 11] EAGAIN

    I don't know if I can obtain more information about the error.

    Thank you very much for offering your help.



  • @M-m Please share the relevant code and logs/traceback pointing to where the issue happens.

    Note that EAGAIN is a standard Unix error code, it can be returned by a lot of other modules completely unrelated to LoRa or LoRaWAN.

    If it is thrown while sending LoRaWAN frames, the main reason for it to be returned is because the LoRaWAN command queue is full. It is unlikely that trying to send again immediately will result in a positive result, quite the contrary.

    You are probably sending too fast. But only seeing the relevant code and logs will tell us.


  • Global Moderator

    Yes, that should solve the issue. Im just thinking that when the LoRa radio gets in this state, it might have stopped responding temporarily, causing the error to occur like this.



  • @Gijs Thank you very much for answering! I'm using lopy4.

    Then if it's the first option, can I solve the problem trying to send it again the message?


  • Global Moderator

    Just to confirm, the behaviour has not changed in the meantime. I cannot really reproduce the error on my side, so if you are able to achieve a stable reproduction let me know!

    From what I understand, there can be indeed 2 causes for the EAGAIN error, the first one being:

        // just pass to the LoRa queue
        if (!xQueueSend(xCmdQueue, (void *)&cmd_data, (TickType_t)(timeout_ms / portTICK_PERIOD_MS))) {
            return 0;
        }
    

    This command passes the packet to the LoRa queue, but if it was unsuccessful, it returns 0. I do not think it is related to the queue being full or the duty cycle, but it's quite vague
    The second one

    else if (result & LORA_STATUS_ERROR) {
                return 0;
            }
    

    checks if the operation (the sending of the packet) returned an error of any sort. This could also have any sort of cause. If you're interested, here's a link to the source code: https://github.com/pycom/pycom-micropython-sigfox/blob/Dev/esp32/mods/modlora.c#L487

    Sorry for my vague description of the error. If you give me the device type you are using (lopy4 / fipy / ..), I can custom compile a firmware version for you with more debug statements so we can find what causes it for you..

    Let me know
    Gijs



Pycom on Twitter