Welcome to the Pycom forum Forum
    • \[\[global:header.categories\]\]
    • \[\[global:header.recent\]\]
    • \[\[global:header.tags\]\]
    • \[\[global:header.popular\]\]
    • Login

    Explore Pybytes | Official Documentation | Report a Firmware Bug/Issue | GitHub

    Issues restoring LoRa state after join() TimeOut

    Scheduled Pinned Locked Moved LoPy
    4 Posts 3 Posters 238 Views 3 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • mnovellaM Offline
      mnovella
      last edited by

      I am having difficulties trying to restore the LoRa state (by calling lora.nvram_restore()) after an attempt to Join times out.

      I've been trying several things, and in my non-LoPy Expert mind, this is would be what I would like to achieve:

      1. Device was previously joined successfully, sent/received data ok, lora.nvram_save() called, shut down.
      2. After that, each time the device tuns on, attempt to Join.
        a. If successful, proceed to create socket and send/recieve.
        b. If TimeOut, call lora.nvram_restore() and proceed to create socket, send/receive.
      3. Call lora.nvram_save() each time data is sent and before shutdown.

      My LoPy is connected to an external power source, and it's initialized as CLASS_C.

      However, after getting a Timeout on the join(), and then calling nvram_restore() I do get True when calling lora.has_joined(). But when I create a socket and then attempt to send data everything freezes, and I have to manually shutdown as Ctrl+C won't work.

      Now, if I skip the whole join attempt part, and immediately call nvram_restore(), I get True on has_joined(), and I also am able to successfully send/receive data after creating the socket. This is what baffles me, as it would seem that calling join() somehow affects what was stored with nvram_save().

      Perhaps I am doing some steps wrong, or missing some detail on the LoRa module Pycom provides? Any guidance or suggestions to be able to achieve what I want ("attempt join else restore on timeout") will be greatly appreciated :)

      Here is the micropython code that implements the pseudo-code above mentioned:

      lora = LoRa(mode=LoRa.LORAWAN, adr=False, device_class=DEVICE_CLASS, region=REGION_US, tx_retries=3)
      #setup the channels specified in my lorasever config
      [lora.remove_channel(channel) for channel in range(0,72)]
      
      [lora.add_channel(channel, frequency=thisFreq, dr_min=0, dr_max=3) for channel, thisFreq in zip(CH_RANGE, FREQ_RANGE)]
      
      try:
          lora.join(activation=LoRa.OTAA, auth=(app_eui, app_key), timeout=some_timeout)
      except Exception as e:
          pass     #timeout 
      
      if lora.has_joined():
          s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)        
          s.setsockopt(socket.SOL_LORA, socket.SO_DR, my_dr)
          #proceed to send/recieve etc. no issues sending here
      else:
          #join timeout
          lora.nvram_restore()
          #lora.has_joined() gives True 
          s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)        
          s.setsockopt(socket.SOL_LORA, socket.SO_DR, my_dr)
          #proceed to send/recieve data. Here is where it FREEZES
      

      Again, if I delete the whole join part and go straight for the restore it works ok.


      Some background:

      This "attempt join else restore state" approach is what I need (?) as I want the device to try join first but have the chance to restore it's state in case it is unable to join promptly for any reason.

      As far as I know, I "need" to do be able to join again to the network eventually, as to obtain new keys and reset the FrameCounter. Otherwise, as my device is on for long amounts of time, and sends data in periods as short as one minute, I did some numbers and I will run out of FrameCounters (65535) in about 20 days.

      Any other info I can provide do tell and I'll gladly include it.

      J 1 Reply Last reply Reply Quote 0
      • J Offline
        jcaron @mnovella
        last edited by

        @mnovella As far as I know, this just won’t work. The saved state is reset when you try to join.

        You could maintain a counter and re-join after a given number of uplinks instead.

        mnovellaM 1 Reply Last reply Reply Quote 0
        • mnovellaM Offline
          mnovella @jcaron
          last edited by

          @jcaron Thanks for your response. Seem you are right. Doing some further test it seems that calling join() erases the nvram.

          I was planning on using lora.stats() to obtain the tx_counter and attempt to rejoin when close to the limit.

          1 Reply Last reply Reply Quote 0
          • T Offline
            Thias
            last edited by Thias

            In general, rejoining for every payload is bad practice. Instead you should always try to restore the LoRa status in favor of a rejoin. I'm also guessing that you heavily violate TTNs Fair Access Policy [1] especially when join requests are added to the air time allowed. Forget this comment in case you are operating on a different LoRaWAN backend provider where other policies apply.

            Secondly, you should give lora.join() some time before testing on has_joined, e.g. in a while loop as proposed here [2]. If your concern is running out of FrameCounters I'd go along with the tx_counter from lora.stats() and rejoin only if you get close to the limit.

            Here's some untested example code:

            lora = LoRa(mode=LoRa.LORAWAN, adr=False, device_class=DEVICE_CLASS, region=REGION_US, tx_retries=3)
            #setup the channels specified in my lorasever config
            [lora.remove_channel(channel) for channel in range(0,72)]
            
            [lora.add_channel(channel, frequency=thisFreq, dr_min=0, dr_max=3) for channel, thisFreq in zip(CH_RANGE, FREQ_RANGE)]
            
            lora.nvram_restore()
            stats = lora.stats()
            
            if not lora.has_joined() or stats['tx_counter'] > 65000:
                lora.join(activation=LoRa.OTAA, auth=(app_eui, app_key), timeout=some_timeout)
                while not lora.has_joined():
                    time.sleep(2.5)
                    print('Not yet joined...')
            
            s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)        
            s.setsockopt(socket.SOL_LORA, socket.SO_DR, my_dr)
            
            

            [1] https://www.thethingsnetwork.org/forum/t/limitations-data-rate-packet-size-30-seconds-uplink-and-10-messages-downlink-per-day-fair-access-policy-guidelines/1300
            [2] https://docs.pycom.io/tutorials/lora/lorawan-otaa/

            1 Reply Last reply Reply Quote 1

            Hello! It looks like you're interested in this conversation, but you don't have an account yet.

            Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.

            With your input, this post could be even better 💗

            Register Login
            • 1 / 1
            • First post
              Last post

            Pycom on Twitter

            Pycom