lora.nvram_restore() OSError: [Errno 122] EMSGSIZE



  • Re: Has anyone successfully used lora.nvram_save() and restore?

    Hi, I'm using a Fipy (firm 1.20.3.b3) on a Pytrack 2.0X to send frame using LoRaWAN in EU868 with OTAA to connect with TTN. And , I want to use the lora methods nvram_save() and nvram_restore() to save my LoRaWAN state before going into deepsleep and restore them.

    And when I wake up after a deepsleep, I use the method restore and check with the method has_joined if I've already joined LoRaWAN before. And then, I try to send a new frame to TTN, I got an error :
    Traceback (most recent call last):
    File "main.py", line 47, in <module>
    OSError: [Errno 122] EMSGSIZE

    My code is bellow :

    from network import LoRa
    import socket
    import time
    import machine
    import ubinascii
    
    # set parameters for sensor function
    lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868)
    lora.nvram_restore()
    if not lora.has_joined():
        print("Firstly join")
        #-------------------- use OTAA to connect with TTN ------------------------------#
        app_eui = ubinascii.unhexlify('xxxxxxxxxxxxxxx')
        app_key = ubinascii.unhexlify('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')
        dev_eui = ubinascii.unhexlify('xxxxxxxxxxxxxxx')
        lora.join(activation=LoRa.OTAA, auth=(dev_eui, app_eui, app_key), timeout=10000) # join a network using OTAA (Over the Air Activation)
        while not lora.has_joined():    # wait until the module has joined the network
            time.sleep(2.5)
            print('Not yet joined...')
        # join in
        print('Successfully join in!')
        #---------- Set LoRa parameters ----------------#
        # 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)
        #---------- Send uplink & Stroe uplink data ----------------#
        uplink_payload = bytes([0x01, 0x02, 0x03])
        s.setblocking(True)
        s.send(uplink_payload)
        s.setblocking(False)
        #time.sleep(1)
        print("")
        lora.nvram_save()   # store in flush to judge next time
        print("####################################")
    
    #-------------------------------- if already join -------------------------------------#
    else:
       
        print("Join already")
        #---------------------------Set LoRa parameters-------------------------------------#
        s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)
        s.setsockopt(socket.SOL_LORA, socket.SO_DR, 5)
        #---------- Send uplink empty ----------------#
        uplink_payload = bytes([0x04, 0x05, 0x06])
        s.setblocking(True)
        s.send(uplink_payload)
        s.setblocking(False)
        print("Send frame after a restore")
        # time.sleep(5)
        lora.nvram_save()
        print("####################################")
    
    print("Deep sleep begin!")
    machine.deepsleep(10000)
    

    If someone knows why I got this error it will be very helpful.



  • @robert-hh Thank you



  • @jcaron OK. Then two nibbles must go into one byte. Like;

    sSend = bytearray(12)
    aSigFox_Bits = [0,0,0,0, 0,0,0,1, 0,0,0,0, 0,0,1,0, 0,0,0,0, 0,0,1,1, 0,0,0,0, 0,1,0,0, 0,0,0,0, 0,1,0,1, 0,0,0,0, 0,1,1,0, 0,0,0,0, 0,1,1,1, 0,0,0,0, 1,0,0,0, 0,0,0,0, 1,0,0,1, 0,0,0,0, 1,0,1,0, 0,0,0,0, 1,0,1,1, 0,0,0,0, 1,1,0,0]
    for i in range(0, 12):
      i8 = i * 8
      byte = 0
      for j in range(8):
            byte = (byte << 1) | aSigFox_Bits[i8 + j] 
      sSend[i] = byte
    print(len(sSend), sSend)
    
    sSend = bytes([0b00000001, 0b00000010, 0b00000011, 0b00000100, 0b00000101, 0b00000110, 0b00000111, 0b00001000, 0b00001001, 0b00001010, 0b00001011, 0b00001100])
    print(len(sSend), sSend)
    


  • @robert-hh I think the goal is to form a 12-byte message (max length of a Sigfox message). Each group of four bits is a nibble, but the conversion from bits to hex to bytes is incorrect.

    Pretty sure there’s a much much simpler way of doing it but I’m not in a mood for Python today…



  • @jcaron The sample string has a length of 24 bytes. Besides that, the loop looks overly complicated. If the input has to be a list of 0/1 values, it could be simplified a little bit to

    sSend = bytearray(24)
    aSigFox_Bits = [0,0,0,0, 0,0,0,1, 0,0,0,0, 0,0,1,0, 0,0,0,0, 0,0,1,1, 0,0,0,0, 0,1,0,0, 0,0,0,0, 0,1,0,1, 0,0,0,0, 0,1,1,0, 0,0,0,0, 0,1,1,1, 0,0,0,0, 1,0,0,0, 0,0,0,0, 1,0,0,1, 0,0,0,0, 1,0,1,0, 0,0,0,0, 1,0,1,1, 0,0,0,0, 1,1,0,0]
    for i in range(0, 24):
      sSend[i] = 8 * aSigFox_Bits[i*4] + 4 * aSigFox_Bits[i*4+1] + 2 * aSigFox_Bits[i*4+2] + aSigFox_Bits[i*4+3]
    print(len(sSend), sSend)
    

    If is is a constant string, it can be written as:

    sSend = bytes([0b0000, 0b0001, 0b0000, 0b0010, 0b0000, 0b0011, 0b0000, 0b0100, 0b0000, 0b0101, 0b0000, 0b0110, 0b0000, 0b0111, 0b0000, 0b1000, 0b0000, 0b1001, 0b0000, 0b1010, 0b0000, 0b1011, 0b0000, 0b1100])
    print(len(sSend), sSend)
    


  • @Jaco-Pretorius I believe this is completely unrelated to the original issue in this thread and is just because your encoding loop is incorrect and results in in a frame which is too long. Print the string and it’s length before sending it, it should be quite obvious.



  • Good day

    I have a similar problem. If try to send the string I get the following error. Any help would be appreciated.

    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    OSError: [Errno 122] EMSGSIZE

    My code:

    import socket
    import pycom
    import time
    from network import Sigfox
    from machine import Timer
    time.sleep(1)
    
    sigfox = Sigfox(mode=Sigfox.SIGFOX, rcz=Sigfox.RCZ1)
    time.sleep(1)
    s = socket.socket(socket.AF_SIGFOX, socket.SOCK_RAW)
    time.sleep(1)
    s.setblocking(True)
    time.sleep(1)
    s.setsockopt(socket.SOL_SIGFOX, socket.SO_RX, True)
    time.sleep(1)
    
    sSend = ""
    aSigFox_Bits = [0,0,0,0, 0,0,0,1, 0,0,0,0, 0,0,1,0, 0,0,0,0, 0,0,1,1, 0,0,0,0, 0,1,0,0, 0,0,0,0, 0,1,0,1, 0,0,0,0, 0,1,1,0, 0,0,0,0, 0,1,1,1, 0,0,0,0, 1,0,0,0, 0,0,0,0, 1,0,0,1, 0,0,0,0, 1,0,1,0, 0,0,0,0, 1,0,1,1, 0,0,0,0, 1,1,0,0]
    for i in range(0, 24):
      iHexChar = 8 * aSigFox_Bits[i*4] + 4 * aSigFox_Bits[i*4+1] + 2 * aSigFox_Bits[i*4+2] + aSigFox_Bits[i*4+3]
      sSend = sSend + str(hex(iHexChar)[2:])
    print(sSend)
    
    s.send(sSend.encode())
    


  • @Etienne-DAL-PRA Thank you very much. This fixed it :)



  • @John-Baxter hi ! Yes of course. I'm sorry for the delay.
    I used the Pycom Firmware Updater (you can download it there https://docs.pycom.io/updatefirmware/device/).
    You need to close Atom or VS Code (the Pymakr console) before doing the upgrade. After you can do the upgrade with the Pycom Firmware Updater, you just need to select the Port and the type of your board.
    Then, I chose as type : Pybytes and as version the lastest : 1.20.2.r4. And selected the options :

    • Erase during update
    • CONFIG partition
    • NVS partition

    And clicked on Continue.

    I hope this helps you if you are still stuck :)



  • @Etienne-DAL-PRA Please can you advise the steps you have taken? I am having a very similar problem and I'm really stuck. Thank you :)



  • @jcaron I've found ! This problem comes from the fact that I flashed the card in "development" mode instead of "pybytes" and I put the version 1.20.2 r0 and it works well.



  • @Gijs Hi, I've already look at the example and it doesn't work too for me.

    The line 47 is the line "s.send(uplink_payload).

    I don't understand why this error appears, is the message size is saved when the nvram_save method is used ?

    @jcaron yes this my actual code to test the nvram_save and nvram_restore methods. I don't think 3 bytes will be out of the LoRaWAN limits.

    I will try without setting the data rate.

    Yes I changed the firmware this week but I didn't try to use these methods before. I will check in that direction too.

    Thank you for your responses :)



  • @Etienne-DAL-PRA is the code above the actual code you are using, especially the data being sent? There are limits on LoRaWAN packets which vary based on region, data rate, and more, but 3 bytes should always be possible, especially in the EU868 region, and even more so at DR5.

    Can you try without setting the data rate, or setting it to different values?

    One thing which may have an influence is the need to send MAC commands (or more likely, responses), but I think it’s quite difficult to get to a point where it would not even allow for 3 bytes of payload (also, I believe payload has precedence over MAC commands).

    Did you change firmware release recently? If so, did you join since then? Not quite sure the format of the LoRaWAN state in NVRAM has remained consistent across versions, it could get the stack in a weird state if not.



  • Have a look at the example for nvram here: https://docs.pycom.io/tutorials/networks/lora/nvram/

    Though I believe your issue has nothing to do with the nvram, but rather with the message size (either too big or too small). I cannot find exactly which line 'line 47' is in the code you attached, but perhaps you can find it yourself :)



Pycom on Twitter