LoRaWAN Sequence Numbers



  • Hi Guys,

    I'm having a problem whereby I can send the very first LoRaWAN data packet to a MultiConnect Conduit gateway device that is connected to LORIOT.io and I can see the packet in the user console log screen, but then all subsequent re-runs of my app on the LoPy do show any more packets getting passed through.

    Apparently the subsequent packets and are actually logged on LORIOT somewhere but are not passed through to the user console etc. Apparently the logs show the packets as having the same Sequence Number (of 1) and so doesn't pass it through.

    Is there any way I can get/set the Sequence Numbers used in the LoRaWAN stack?
    If not then can this be added?

    Exposing the other LoRaWAN stack settings like the SF DR etc might be useful while we are having to experiment with get the LoPy working well over LoRaWAN with the different gateway devices as it seems they are not all created or configured equally and so the ability to do some tweaks are needed...



  • @kots As @jmarcelino said, just call lora.nvram_save() before going to deep sleep, and lora.nvram_restore() after initialising LoRa but before sending your message.



  • @jmarcelino Thanks!
    Any idea how they work?



  • @kots
    In the latest firmware you can now use lora.nvram_save() to save your current frame counters and then lora.nvram_restore() to restore them again after power-on/reset.



  • hello!
    Anyone who found how to solve this problem?



  • I was able to solve my problem, and now having seamless uplinks and downlinks. There was a issue with my channels settings that the gateway supported.
    Also was having issues with pymakr with uploading code to lopy which caused delay in code testing. Now compeletly abandoned pymakr and moved to transfer file using FTP.



  • @kiwi64ajs I've written an add-on for the firmware to allow setting the uplink counter. I need to test it tomorrow (I don't have a functional gateway at home)--assuming it works, I'll create a pull request.



  • @bmarkus
    I disagree, for mobile devices in particular the advantages of OTAA (provisioning setup inc. counter reliability and added security) outweigh the disadvantages.

    Here's a big problem with ABP: imagine you leave an active ABP node outside of reach of a gateway for a while. The frame counter on the node will keep on ticking, increasing the difference between it and what the backend expects. According to the spec once this difference goes over the allowed range (just 16384 packets for TTN) the backend will start rejecting any further packets. If you send a packet every minute this happens in less 12 days, a realistic scenario for a mobile LoRa device.

    This would then have to be detected and counters manually reset at both node and backend. A provisioning nightmare if you have devices in the hands of users!

    With OTAA once the node receives a join response you can be sure 1) there's coverage and 2) the data you send will match up, no guessing if you have stale encryption keys or frame counters. Also if you receive a fail response from the backend your node can alert the user.

    To me there's just a small set of use cases where you really need ABP and for most applications - especially if you're deploying devices to other users and want to sleep at night - OTAA really is the way to go.



  • @kiwi64ajs Yep, I'm developing a product for a commercial LoRaWAN and they have provided a nano gateway from orbiwise and on the server I can only view the data, no server settings are exposed, may be I'll too have a gateway setup for the product demo if this doesn't work.

    One more option its to edit and compile the firmware and try exposing it at app level, don't know how that will go, but I'll give it a try.

    Thanks again for your code, it really made my day to see that one frame being uploaded to my server. :)
    Cheers!!



  • @jmarcelino said in LoRaWAN Sequence Numbers:

    The recommended way is really to use OTAA and do a join at every reset, so you get fresh counter and don't have to worry about this

    Depends on your use case. OTAA is good for fixed sensor devices, but for e.g. moving mobile devices (trackers) doesn't, there ABP is the proper method.



  • I agree these settings should be exposed somewhere (and both the UpLinkCounter and DownLinkCounter!) but please take care if making them restore automatically - and if so definitely make it optional.

    The Flash chip is only specced for 100,000 erase/program cycles, so if you're updating the frame counter in Flash every time and you send a frame for example every 5 minutes the Flash would only last one year.

    The recommended way is really to use OTAA and do a join at every reset, so you get fresh counter and don't have to worry about this. In this case storing the counters would be of no use.

    If you really want to store your counters I suggest some external FRAM (Ferroelectric) which is good for 10 trillion cycles. There are easy to use chips with I2C and ready made breakouts for prototyping.



  • @hemalchevli said in LoRaWAN Sequence Numbers:

    Hi Alex,
    I was struggling to get the data to server, using your code you shared it worked once, I don't have debug information from the server side. Were you able to fix the issue?
    I'm a newbie in python, where can I find the fcnt or sequence number variable?

    No and there does not seem to be anyway to really fix this at an application level unless the check at the server is turned off - which is NOT ideal.

    The stack could cache the last used number in EEPROM / FLASH and resume from there next time, but we don't have get/set access the sequence number at the API level so I don't know what to do next.

    This is a problem when you're trying to develop a product against a commercial LoRaWAN service provider who does have the sequence number check enabled... Guess I need my own LoRaWAN Gateway with the sequence check turned off for now

    Alex



  • @Antony said in LoRaWAN Sequence Numbers:

    Incrementing the sequence number is mandatory in the LoRaWAN spec, and is necessary for devices to be secure. Hacking this at the Loriot server isn't a good solution. Alex, what you say is right - you need to cache the sequence number counter and then restore it. Or even better, the stack would do it for you.

    But I don't see anything in the Pycom LoRa API that makes it possible to do this? For example, it could be done through socket.setsockopt() but there is no mention of this in the (1.8.4) documentation.

    Should this be submitted as a bug?

    Antony

    In other cases, like RN2483 sequence number is incremented by the LoRaWAN stack and not by the application.

    At the Loriot server it is a great feature to disable sequence number during development, it saves you hours. Agree, in production system it is not adviced.



  • Incrementing the sequence number is mandatory in the LoRaWAN spec, and is necessary for devices to be secure. Hacking this at the Loriot server isn't a good solution. Alex, what you say is right - you need to cache the sequence number counter and then restore it. Or even better, the stack would do it for you.

    But I don't see anything in the Pycom LoRa API that makes it possible to do this? For example, it could be done through socket.setsockopt() but there is no mention of this in the (1.8.4) documentation.

    Should this be submitted as a bug?

    Antony



  • Hi Alex,
    I was struggling to get the data to server, using your code you shared it worked once, I don't have debug information from the server side. Were you able to fix the issue?
    I'm a newbie in python, where can I find the fcnt or sequence number variable?
    Thanks
    Cheers!



  • Hello @kiwi64ajs

    Thank you so much for your code snippet. We are facing the similar issue of duplication of packets. Did you solved the problem?



  • @bmarkus said in LoRaWAN Sequence Numbers:

    If LoPy is not incrementing FCNT it is a bug in the LoRaWAN stack implementation.

    Well the issue is my code start, connects and sends the data and then exist. The first run is ok, but any subsequent runs restarts the lora stack and the Sequence starts from 1 again, which is fine for the sender, but the receiving end at the server see packets with the same Sequence number and assumes they are duplicates, which is not so not good from the sender's perspective, but ignoring the duplicate Sequence numbers if not a good thing either from a robustness perspective.

    I changed my code to send packets in a loop and the Sequence number IS being incremented each time it goes around the loop, but if I run and then exit and then run again the Stack only send one packet per run and so the Sequence restarts from 1 each time.

    Being able to manage (get, persist, restore, set) the Sequence numbers used in the LoRa stack is probably a better approach. That way the developer has some choices about how best to manage this issue.



  • @bmarkus

    Hmmm... couldn't figure out how to attach a file so hopefully this works... ;)

    from network import LoRa
    from socket import *
    import socket
    import binascii
    import struct
    import os
    
    print('Begin LoRaWAN Connection Test')
    print
    # Initialize LoRa in LORAWAN mode.
    lora = LoRa(mode=LoRa.LORAWAN, sf=7)
    
    print("Board Info")
    b = os.uname()
    print('Sysname: ',  b.sysname)
    print('Nodeame: ',  b.nodename)
    print('Release: ',  b.release)
    print('Version: ',  b.version)
    print('Machine: ',  b.machine)
    print
    
    print('LoRa MAC: ', end="")
    print(binascii.hexlify(lora.mac()).upper().decode('utf-8'))
    
    print('Setup channels')
    lora.add_channel(0, frequency=865000000, dr_min=0, dr_max=5, duty_cycle=0)
    lora.add_channel(1, frequency=865200000, dr_min=0, dr_max=5, duty_cycle=0)
    lora.add_channel(2, frequency=865400000, dr_min=0, dr_max=5, duty_cycle=0)
    lora.add_channel(3, frequency=866200000, dr_min=0, dr_max=5, duty_cycle=0)
    lora.add_channel(4, frequency=866400000, dr_min=0, dr_max=5, duty_cycle=0)
    lora.add_channel(5, frequency=866600000, dr_min=0, dr_max=5, duty_cycle=0)
    lora.add_channel(6, frequency=866800000, dr_min=0, dr_max=5, duty_cycle=0)
    lora.add_channel(7, frequency=867000000, dr_min=0, dr_max=5, duty_cycle=0)
    lora.remove_channel(8)
    lora.remove_channel(9)
    lora.remove_channel(10)
    lora.remove_channel(11)
    lora.remove_channel(12)
    lora.remove_channel(13)
    lora.remove_channel(14)
    lora.remove_channel(15)
    
    print('Setup keys')
    # create an ABP authentication params
    dev_addr =  struct.unpack(">l", binascii.unhexlify('00000000'))[0]
    nwk_swkey = binascii.unhexlify('00000000000000000000000000000000')
    app_swkey = binascii.unhexlify('00000000000000000000000000000000')
    
    print('Join LoRaWAN')
    # join a network using ABP (Activation By Personalization)
    lora.join(activation=LoRa.ABP, auth=(dev_addr, nwk_swkey, app_swkey))
    
    # wait until the module has joined the network
    while not lora.has_joined():
        time.sleep(1)
        print('Waiting to Join LoRaWAN Network...')
    
    print('Setup Socket')
    # 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, 0)
    s.setsockopt(socket.SOL_LORA, socket.SO_CONFIRMED, False)
    
    s.setblocking(True)   # Make the socket blocking, socket.send() won't return until completed
    s.settimeout(5)     # Configure the timeout of the socket
    
    print('Sending Data... ', end="")
    
    # Try sending some data
    try:
        s.send('Hello World')
    
        print('Complete')
    except timeout:
       print("Timeout Sending Data")
    
    # Check to see if there is any data waiting for us to Receive..
    try:
        print('Try to Receive Data... ', end="")
    
        data = s.recv(64)
    
        print('Received Data: ', end="")
        print(data)
    except timeout:
       print("No Data Received")
    
    print('Test Complete')
    


  • Alex

    would you mind to share your code?

    Regards... Béla



  • If LoPy is not incrementing FCNT it is a bug in the LoRaWAN stack implementation.

    Login to your loriot.io account and select your device in Dashboard > Applications > SampleApp menu. In the lower right corner you find LoRaWAN Sequence numbers settings, disable Seqno checking. By default it is enabled (strict) to protect network against buggy devices like LoPy.


Log in to reply
 

Pycom on Twitter