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

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

    Scheduled Pinned Locked Moved LoPy
    lopyloranvram
    17 Posts 7 Posters 4.9k Views 9 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.
    • J Offline
      jmarcelino @jalperin
      last edited by jmarcelino

      @jalperin

      Try to restore your channel frequency configuration manually again after the nvram_restore, just use your existing code:

      for channel in range(0, 72):
          lora.remove_channel(channel)
      for chan in range(0, 8):
          lora.add_channel(chan, frequency=freq, dr_min=0, dr_max=3)
      

      The current nvram_save() may not save this...

      J B 2 Replies Last reply Reply Quote 0
      • J Offline
        jalperin @jmarcelino
        last edited by jalperin

        @jmarcelino

        Restoring the channel configuration did the trick. Setblocking(True) was not needed here.

        An anomaly that I have seen before showed up. The packets sent after nvram_restore all arrived with "payload not provided". But, if I first send a packet with a payload of a single character, it and all subsequent packets arrive successfully.

        May I suggest that the documentation be amended to detail what is and is not saved by lora.nvram_save().

        Thank you very much for your help.

        J 1 Reply Last reply Reply Quote 0
        • J Offline
          johncaipa @jalperin
          last edited by

          @jalperin @jmarcelino works but the counter is restarted on each send, this value is not stored?

          bmarkusB 1 Reply Last reply Reply Quote 0
          • bmarkusB Offline
            bmarkus @johncaipa
            last edited by

            @johncaipa said in Has anyone successfully used lora.nvram_save() and restore?:

            @jalperin @jmarcelino works but the counter is restarted on each send, this value is not stored?

            Unfortunately it is not possible to get or set your own FCnt value, otherwise it would be possible to handle in your code. Just one of the several missing LoRa/LoRaWAN functions.

            J 1 Reply Last reply Reply Quote 0
            • J Offline
              johncaipa @bmarkus
              last edited by

              @bmarkus in the documentation says that this value is saved, then I do not know what would be the problem, because in each sending after waking up the packet counters is always in 1 on TTN.
              "lora.nvram_save()
              Save the LoRaWAN state (joined status, network keys, packet counters, etc) in non-volatile memory in order to be able to restore the state when coming out of deepsleep or a power cycle."

              bmarkusB 1 Reply Last reply Reply Quote 0
              • bmarkusB Offline
                bmarkus @johncaipa
                last edited by

                @johncaipa said in Has anyone successfully used lora.nvram_save() and restore?:

                @bmarkus in the documentation says that this value is saved, then I do not know what would be the problem, because in each sending after waking up the packet counters is always in 1 on TTN.
                "lora.nvram_save()
                Save the LoRaWAN state (joined status, network keys, packet counters, etc) in non-volatile memory in order to be able to restore the state when coming out of deepsleep or a power cycle."

                Do you create a new instance when coming out? It resets the counter.

                J 1 Reply Last reply Reply Quote 0
                • J Offline
                  johncaipa @bmarkus
                  last edited by

                  @bmarkus this is the example code I'm testing, based on which share @jalperin, I'm missing something?

                  from network import LoRa
                  import struct
                  import binascii
                  import time
                  import math
                  import pycom
                  import socket
                  from pysense import Pysense

                  py = Pysense()
                  loraSaved = pycom.nvs_get('loraSaved')
                  print(loraSaved)
                  if not loraSaved:
                  lora = LoRa(mode=LoRa.LORAWAN)
                  freq = 902300000
                  for channel in range(0, 72):
                  lora.remove_channel(channel)
                  for chan in range(0, 8):
                  lora.add_channel(chan, frequency=freq, dr_min=0, dr_max=3)

                  dev_addr = struct.unpack(">l", binascii.unhexlify('************'.replace(' ','')))[0]
                  nwk_swkey = binascii.unhexlify('************ 89 F1 74 79 40'.replace(' ',''))
                  app_swkey = binascii.unhexlify('************ 3A AA BD E8 A9'.replace(' ',''))
                  lora.join(activation=LoRa.ABP, auth=(dev_addr, nwk_swkey, app_swkey))
                  while not lora.has_joined():
                      machine.idle()
                  s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)
                  s.setsockopt(socket.SOL_LORA, socket.SO_DR, 3)
                  s.bind(3) #select the port number
                  s.setblocking(False)
                  s.send('LoRa Up')
                  time.sleep(2)
                  lora.nvram_save()
                  pycom.nvs_set('loraSaved', 1)
                  py.setup_sleep(60)
                  py.go_to_sleep()
                  

                  else:
                  lora = LoRa(mode=LoRa.LORAWAN)
                  lora.nvram_restore()
                  freq = 902300000
                  for channel in range(0, 72):
                  lora.remove_channel(channel)
                  for chan in range(0, 8):
                  lora.add_channel(chan, frequency=freq, dr_min=0, dr_max=3)
                  s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)
                  s.setsockopt(socket.SOL_LORA, socket.SO_DR, 3)
                  s.bind(3) #select the port number
                  s.setblocking(False)
                  s.send('LoRa Restored')
                  time.sleep(2)
                  lora.nvram_save()
                  #pycom.nvs_set('loraSaved', 0) # reset for next test
                  py.setup_sleep(60)
                  py.go_to_sleep()

                  1 Reply Last reply Reply Quote 0
                  • R Offline
                    rloro338
                    last edited by

                    I am trying to use lora.nvram_save() and lora.nvram_restore() and not works. I set all parameters (LoRaWAN, adr = True, app_eui, app_key and channel configuration) the first time that I boot the device and send a message Loriot server receive it. Then device go to deepsleep for 5 seconds and restore the join state. If I look the state with lora.has_joined() return True value, but when I trying to send the message it isn't received by the gateway.

                    It is curious because when I use the node directly with a command line in Putty the restore and save comands works fine.

                    What I am doing wrong??

                    J 1 Reply Last reply Reply Quote 0
                    • J Offline
                      johncaipa @rloro338
                      last edited by

                      @rloro338 I made the following changes to my code and now it works correctly:

                      • list item make sure the socket is blocking ( s.setblocking(True) )

                      • list item add a time.sleep(2) after sending, before saving and going to deep sleep.

                      1 Reply Last reply Reply Quote 0
                      • B Offline
                        Bismarck501 @jmarcelino
                        last edited by

                        @jmarcelino Hello, I have read your suggestion carefully and tried in my project. But there was some issues about this solution.
                        My device consists of FiPy+pysense, and I connected to TTN via OTAA. My code with lora,nvram_save() and restore() is:

                        # pysense sensor part
                        from pysense import Pysense
                        from LTR329ALS01 import LTR329ALS01
                        from LIS2HH12 import LIS2HH12
                        
                        # FiPy part
                        from network import LoRa
                        import socket
                        import time
                        import pycom
                        import ubinascii
                        import machine
                        
                        # pysense machine part
                        from machine import RTC
                        from machine import SD
                        import os
                        
                        from network import WLAN, Bluetooth,LTE
                        
                        # set parameters for sensor function
                        py = Pysense()
                        lt = LTR329ALS01(py)  # only use light sensor
                        
                        
                        loraSaved = pycom.nvs_get('loraSaved')  # if join already, it is int 3; or it will be None
                        #-------------------------------- if already join -------------------------------------#
                        if (loraSaved == 11):
                        
                            lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868)
                        
                            lora.nvram_restore()
                            #--------- Remove default channels ----------#
                            for index in range(0, 15):
                                lora.remove_channel(index)
                            lora.add_channel(3, frequency=867100000, dr_min=0, dr_max=5)
                            lora.add_channel(4, frequency=867300000, dr_min=0, dr_max=5)
                            lora.add_channel(5, frequency=867500000, dr_min=0, dr_max=5)
                            lora.add_channel(6, frequency=867700000, dr_min=0, dr_max=5)
                            lora.add_channel(7, frequency=867900000, dr_min=0, dr_max=5)
                        
                            lora.add_channel(8, frequency=868100000, dr_min=0, dr_max=5)
                            lora.add_channel(9, frequency=868300000, dr_min=0, dr_max=5)
                            lora.add_channel(10, frequency=868500000, dr_min=0, dr_max=5)
                            lora.add_channel(11, frequency=868700000, dr_min=0, dr_max=5)
                            lora.add_channel(12, frequency=868900000, dr_min=0, dr_max=5)
                        
                            lora.add_channel(13, frequency=869100000, dr_min=0, dr_max=5)
                            lora.add_channel(14, frequency=869300000, dr_min=0, dr_max=5)
                            lora.add_channel(15, frequency=869500000, dr_min=0, dr_max=5)
                        
                            print("Join already")
                            #--------------------------------------------------------------------------------#
                            #						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 = ("Light: " + str(lt.light()))
                            s.setblocking(True)
                            s.send(uplink_payload)
                            lora.nvram_save()
                            print("send finish")
                            
                            #--------- Receive downlink & Stroe downlink data ----------#
                            s.setblocking(False)
                            downlink_message = s.recv(64) # bytes form     and     n is typically < 64 bytes
                            time.sleep(1)
                            print(downlink_message)
                            print(type(downlink_message))
                            print("Receive finish")
                        
                            #----------- Jugde whether there is a downlink -------------#
                            if downlink_message == b'':
                                print("There is no downlink")
                            else:
                                downlink_payload = downlink_message.decode('ascii') # string form
                                print("Downlink message: " + downlink_payload)
                                #-------- Judge downlink message & operate -------------#
                                if downlink_message == b'2': # if ==2, it will light green for 5 seconds
                                    print("Hi, Green!")
                                    pycom.rgbled(0x007f00) # green
                                    time.sleep(3)
                                if downlink_message == b'4': # if ==4, it will light yellow for 5 seconds
                                    print("Hi, Yellow!")
                                    pycom.rgbled(0x7f7f00) # yellow
                                    time.sleep(3)
                            print("####################################")
                            print("\n")
                        
                        #-------------------------------- if never join before -------------------------------------#
                        else:
                            print("Firstly join")
                            #--------------------------------------------------------------------------------#
                            # 					Initialise LoRa in LORAWAN mode.
                            lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868)
                            #--------------------------------------------------------------------------------#
                            #				Set OTAA mode and connect with the gateway
                            # create an OTAA authentication parameters
                            app_eui = ubinascii.unhexlify('70B3D57ED0013E78')
                            app_key = ubinascii.unhexlify('5D87FAB0BC66A45FB0DA07453ED2BC2B')
                            # join a network using OTAA (Over the Air Activation)
                            lora.join(activation=LoRa.OTAA, auth=(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...')
                            # 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 = ("Light: " + str(lt.light()))
                            s.setblocking(True)
                            s.send(uplink_payload)
                            lora.nvram_save()
                        
                            #--------- Receive downlink & Stroe downlink data ----------#
                            s.setblocking(False)
                            downlink_message = s.recv(64) # bytes form     and     n is typically < 64 bytes
                            #time.sleep(1)
                            print(downlink_message)
                            print(type(downlink_message))
                        
                            #----------- Jugde whether there is a downlink -------------#
                            if downlink_message == b'':
                                print("There is no downlink")
                            else:
                                downlink_payload = downlink_message.decode('ascii') # string form
                                print("Downlink message: " + downlink_payload)
                        
                                #-------- Judge downlink message & operate -------------#
                                if downlink_message == b'2': # if ==2, it will light green for 5 seconds
                                    print("Hi, Green!")
                                    pycom.rgbled(0x007f00) # green
                                    time.sleep(3)
                                if downlink_message == b'4': # if ==4, it will light yellow for 5 seconds
                                    print("Hi, Yellow!")
                                    pycom.rgbled(0x7f7f00) # yellow
                                    time.sleep(3)
                            print("####################################")
                            print("\n")
                            #---------- store in flush to judge next time ----------------#
                            pycom.nvs_set('loraSaved', 11)  
                        # time sleep
                        py.setup_sleep(9)   # setup a 9 seconds sleep time
                        py.go_to_sleep()
                        
                        
                        

                        And it can work well. However, after one day, when I tried again, there would be an issue when running code at line 65:

                            s.send(uplink_payload)
                        

                        3885de5c-2262-4686-b6bf-bedc703c6446-image.png

                        Where I was wrong? Thanks for giving me some advice!

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

                          @Bismarck501 You should factorise your code a lot, it would make things a lot easier to maintain.

                          You shouldn't rely on an additional NVRAM variable to determine your LoRaWAN state.

                          Instead, just call nvram_restore, then has_joined. If not true, you need to join. Otherwise, you can go ahead and send/receive.

                          Also, I would call nvram_save after any interaction with the LoRaWAN stack is finished including the recv part. Not sure it currently causes any issues, but it's better to be consistent.

                          B 2 Replies Last reply Reply Quote 0
                          • B Offline
                            Bismarck501 @jcaron
                            last edited by

                            @jcaron Thanks for responsing so quick! I have tried your suggestion and it works now. And I will experiment further to eusure the stability. Now the code is:

                            # pysense sensor part
                            from pysense import Pysense
                            from LTR329ALS01 import LTR329ALS01
                            from LIS2HH12 import LIS2HH12
                            
                            # FiPy part
                            from network import LoRa
                            import socket
                            import time
                            import pycom
                            import ubinascii
                            import machine
                            
                            # pysense machine part
                            from machine import RTC
                            from machine import SD
                            import os
                            
                            from network import WLAN, Bluetooth,LTE
                            
                            # set parameters for sensor function
                            py = Pysense()
                            lt = LTR329ALS01(py)  # only use light sensor
                            
                            lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868)   # itialise LoRa in LORAWAN mode.
                            lora.nvram_restore()
                            #-------------------------------- if never join before -------------------------------------#
                            if not lora.has_joined():
                                print("Firstly join")
                                #-------------------- use OTAA to connect with TTN ------------------------------#
                                app_eui = ubinascii.unhexlify('70B3D57ED0013E78')
                                app_key = ubinascii.unhexlify('5D87FAB0BC66A45FB0DA07453ED2BC2B')
                                lora.join(activation=LoRa.OTAA, auth=(app_eui, app_key), timeout=0) # 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 = ("Light: " + str(lt.light()))
                                s.setblocking(True)
                                s.send(uplink_payload)
                            
                                #--------- Receive downlink & Stroe downlink data ----------#
                                s.setblocking(False)
                                downlink_message = s.recv(64) # bytes form     and     n is typically < 64 bytes
                                #time.sleep(1)
                                print(downlink_message)
                                print(type(downlink_message))
                                lora.nvram_save()   # store in flush to judge next time
                            
                                #----------- Jugde whether there is a downlink -------------#
                                if downlink_message == b'':
                                    print("There is no downlink")
                                else:
                                    downlink_payload = downlink_message.decode('ascii') # string form
                                    print("Downlink message: " + downlink_payload)
                                    #-------- Judge downlink message & operate -------------#
                                    if downlink_message == b'2': # if ==2, it will light green for 5 seconds
                                        print("Hi, Green!")
                                        pycom.heartbeat(False)
                                        pycom.rgbled(0x007f00) # green
                                        time.sleep(3)
                                        pycom.heartbeat(True)
                                    if downlink_message == b'4': # if ==4, it will light yellow for 5 seconds
                                        print("Hi, Yellow!")
                                        pycom.heartbeat(False)
                                        pycom.rgbled(0x7f7f00) # yellow
                                        time.sleep(3)
                                        pycom.heartbeat(True)
                                print("####################################")
                                print("\n")
                            
                            #-------------------------------- if already join -------------------------------------#
                            else:
                                '''
                                #--------- Remove default channels ----------#
                                for index in range(0, 15):
                                    lora.remove_channel(index)
                                lora.add_channel(3, frequency=867100000, dr_min=0, dr_max=5)
                                lora.add_channel(4, frequency=867300000, dr_min=0, dr_max=5)
                                lora.add_channel(5, frequency=867500000, dr_min=0, dr_max=5)
                                lora.add_channel(6, frequency=867700000, dr_min=0, dr_max=5)
                                lora.add_channel(7, frequency=867900000, dr_min=0, dr_max=5)
                            
                                lora.add_channel(8, frequency=868100000, dr_min=0, dr_max=5)
                                lora.add_channel(9, frequency=868300000, dr_min=0, dr_max=5)
                                lora.add_channel(10, frequency=868500000, dr_min=0, dr_max=5)
                                lora.add_channel(11, frequency=868700000, dr_min=0, dr_max=5)
                                lora.add_channel(12, frequency=868900000, dr_min=0, dr_max=5)
                            
                                lora.add_channel(13, frequency=869100000, dr_min=0, dr_max=5)
                                lora.add_channel(14, frequency=869300000, dr_min=0, dr_max=5)
                                lora.add_channel(15, frequency=869500000, dr_min=0, dr_max=5)
                                '''
                                print("Join already")
                                #---------------------------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 = ("Light: " + str(lt.light()))
                                s.setblocking(True)
                                s.send(uplink_payload)
                                print("send finish")
                            
                                #--------- Receive downlink & Stroe downlink data ----------#
                                s.setblocking(False)
                                downlink_message = s.recv(64) # bytes form     and     n is typically < 64 bytes
                                time.sleep(1)
                                print(downlink_message)
                                print(type(downlink_message))
                                lora.nvram_save()
                                print("Receive finish")
                            
                                #----------- Jugde whether there is a downlink -------------#
                                if downlink_message == b'':
                                    print("There is no downlink")
                                else:
                                    downlink_payload = downlink_message.decode('ascii') # string form
                                    print("Downlink message: " + downlink_payload)
                            
                                    #-------- Judge downlink message & operate -------------#
                                    if downlink_message == b'2': # if ==2, it will light green for 5 seconds
                                        print("Hi, Green!")
                                        pycom.heartbeat(False)
                                        pycom.rgbled(0x007f00) # green
                                        time.sleep(3)
                                        pycom.heartbeat(True)
                                    if downlink_message == b'4': # if ==4, it will light yellow for 5 seconds
                                        print("Hi, Yellow!")
                                        pycom.heartbeat(False)
                                        pycom.rgbled(0x7f7f00) # yellow
                                        time.sleep(3)
                                        pycom.heartbeat(True)
                                print("####################################")
                                print("\n")
                            
                            print("Deep sleep begin!")
                            # time sleep
                            py.setup_sleep(9)   # setup a 10 seconds sleep time
                            py.go_to_sleep()
                            #machine.deepsleep(9000)  # machine.deepsleep([milli_sec])
                            

                            Thanks a lot!

                            1 Reply Last reply Reply Quote 0
                            • B Offline
                              Bismarck501 @jcaron
                              last edited by

                              @jcaron The issue has been worked out and it works quite well now! Thanks a lot!

                              1 Reply Last reply Reply Quote 0

                              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