lora.nvram_save / restore() | frame counter updates
-
Hey guys,
I'm running a node which is a pycom lopy4 + pysense and i'm joining a lora session and saving that sessions sending values and restoring the lora session what i want to ask is:
- does the session expires? if yes when (at what time)?
- how can i update the frame counter? because i'm always reading the frame 0 despite the information being correct...
- i have the tag "retry" in the application traffic; what's the consequence of this?
Thank you guys!
that's my code there:
################################################# General color code ################################################# # pycom.rgbled(0x007f00) -> green = <action> accepted # pycom.rgbled(0x7f7f00) -> yellow = <action> pending # pycom.rgbled(0x7f0000) -> red = <action> gone wrong ###################################################################################################################### ##################################################### Libraries ###################################################### from network import LoRa from network import WLAN import machine import socket import ubinascii import struct import time import config import pycom from pysense import Pysense from deepsleep import DeepSleep import deepsleep from LIS2HH12 import LIS2HH12 from SI7006A20 import SI7006A20 from LTR329ALS01 import LTR329ALS01 from MPL3115A2 import MPL3115A2,ALTITUDE,PRESSURE from math import log from struct import * import base64 import gc pycom.heartbeat(False) # turn off the heartbeat to make way for control pulses in rgb print("Starting sequence initiated...") pycom.rgbled(0x7f0000) #red = <action> not forwarded time.sleep(1) pycom.rgbled(0x007f00) # green = <action> accepted print("Off you go!") #Sensor instances created py = Pysense() mpp = MPL3115A2(py,mode=PRESSURE) # Returns height in meters. Mode may also be set to PRESSURE, returning a value in Pascals si = SI7006A20(py) # temp, humidity lt = LTR329ALS01(py) # light li = LIS2HH12(py) # accelerometer ds=DeepSleep() #gc.enable() # enable garbage collection # initialize 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 OTA authentication params # dev_eui = ubinascii.unhexlify('70B3D54995F6E9F1') # these settings can be found from TTN # app_eui = ubinascii.unhexlify('70B3D57ED0019C87') # these settings can be found from TTN 'o que estava aantes -- 70B3D57ED0019813' # app_key = ubinascii.unhexlify('169C2EF739EAAF4051CD16B8CDA3D56A') # these settings can be found from TTN # # # set the 3 default channels to the same frequency (must be before sending the OTAA join request) # lora.add_channel(0, frequency=config.LORA_FREQUENCY, dr_min=0, dr_max=5) # lora.add_channel(1, frequency=config.LORA_FREQUENCY, dr_min=0, dr_max=5) # lora.add_channel(2, frequency=config.LORA_FREQUENCY, dr_min=0, dr_max=5) # # # join a network using OTAA # lora.join(activation=LoRa.OTAA, auth=(dev_eui, app_eui, app_key), timeout=0, dr=config.LORA_NODE_DR) # # # wait until the module has joined the network # while not lora.has_joined(): # time.sleep(2.5) # pycom.rgbled(0x7f7f00) # yellow = lora.join pending # print('Not joined yet...') # print('LoRa joined!') # pycom.rgbled(0x007f00) # green = lora.join complete # # # remove all the non-default channels # for i in range(3, 16): # lora.remove_channel(i) # # # 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, config.LORA_NODE_DR) # # # make the socket non-blocking # s.setblocking(False) # # time.sleep(5.0) ################################################ Funcoes de configuracao ############################################# # Input: void # Output: None - LoRaWAN join # Join to LoRaWAN session def join_LoRaWAN(): lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868) # create an OTA authentication params dev_eui = ubinascii.unhexlify('70B3D54995F6E9F1') # these settings can be found from TTN app_eui = ubinascii.unhexlify('70B3D57ED0019C87') # these settings can be found from TTN 'o que estava aantes -- 70B3D57ED0019813' app_key = ubinascii.unhexlify('169C2EF739EAAF4051CD16B8CDA3D56A') # these settings can be found from TTN # set the 3 default channels to the same frequency (must be before sending the OTAA join request) lora.add_channel(0, frequency=config.LORA_FREQUENCY, dr_min=0, dr_max=5) lora.add_channel(1, frequency=config.LORA_FREQUENCY, dr_min=0, dr_max=5) lora.add_channel(2, frequency=config.LORA_FREQUENCY, dr_min=0, dr_max=5) # join a network using OTAA lora.join(activation=LoRa.OTAA, auth=(dev_eui, app_eui, app_key), timeout=0, dr=config.LORA_NODE_DR) # wait until the module has joined the network while not lora.has_joined(): time.sleep(2.5) pycom.rgbled(0x7f7f00) # yellow = lora.join pending print('Not joined yet...') print('LoRa joined!') pycom.rgbled(0x007f00) # green = lora.join complete # remove all the non-default channels for i in range(3, 16): lora.remove_channel(i) # 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, config.LORA_NODE_DR) # make the socket non-blocking s.setblocking(False) time.sleep(5.0) return s # Input: void # Output: None - WLAN join # Join to a WLAN of choice def join_WLAN(): wlan = WLAN(mode=WLAN.STA) nets = wlan.scan() pycom.rgbled(0x7f7f00) # yellow = scanning networks time.sleep(1) print("Scanning networks...") time.sleep(1) for net in nets: if net.ssid == WIFI_SSID: print('Network found!') wlan.connect(net.ssid, auth=(net.sec, WIFI_PASS), timeout=5000) # while not wlan.isconnected(): # machine.idle() # save power while waiting print('WLAN connection succeeded!') pycom.rgbled(0x007f00) # green = wlan.connect accepted break # Input: void # Output: None - RTC synchronized # Sincronizacao com RTC def sync_RTC(): rtc=machine.RTC() time.sleep(1) pycom.rgbled(0x7f7f00) # yellow = rtc.ntp_sync pending print("Synchronizing RTC ...") time.sleep(1) rtc.ntp_sync('pool.ntp.org',3600) while not rtc.synced(): # beware: maybe add counter if unsynced ntp doesn't lead to infinite loop rtc.ntp_sync('pool.ntp.org',3600) pycom.rgbled(0x7f0000) #red = <action> not forwarded print("RTC still not synchronized...") time.sleep(2.5) print("RTC synchronized!") time.sleep(2.5) pycom.rgbled(0x2b14c6) time.sleep(2.5) pycom.rgbled(0x007f00) # green = rtc.ntp_sync accepted ALTHOUGH rtc.synced() == False time.sleep(1) print("Prepare for TAKEOFF!") time.sleep(1) return ###################################################################################################################### ################################################# Funcoes auxiliares ################################################# # Input: valor n # Output: Número de bytes necessários para codificar o valor n # Funcao auxiliar de calculo ao nº de bytes necessarios para codificacao de um dado valor def bytes_needed(n): if n == 0: return 1 return int(log(n, 256)) + 1 # int(log(n, 2)) + 1 para calcular nº de bits necessarios ###################################################################################################################### ################################################# Funcoes de sensor ################################################## # Input: void # Output: lista contendo valores lidos em posicoes fixas # Leitura de sensores num determinado instante def readSensor(): list=[] acc_x = li.acceleration()[0] acc_y = li.acceleration()[1] acc_z = li.acceleration()[2] pitch = li.pitch() # [-90, 90]; Unidades: graus roll = li.roll() # [-180, 180]; Unidades: graus humid = int(round(si.humidity()*10)) # arredondamento a uma casa decimal; Unidades: % temp = int(round((si.temperature()+273.15)*10)) # arredondamento a uma casa decimal; Unidades: K light = lt.light()[0] light1 = lt.light()[1] press=int(mpp.pressure()/100) # descodificação a /100; Unidades: kPa com 1 casa decimal batt = int(py.read_battery_voltage()*10) # Unidades: dV list.append(acc_x) list.append(acc_y) list.append(acc_z) list.append(pitch) list.append(roll) list.append(humid) list.append(temp) list.append(light) list.append(light1) list.append(press) list.append(batt) return list def encoder(v, f): bytes=bytearray() values=v formats=f for i in range(len(values)): bytes.extend(struct.pack(formats[i], values[i])) return bytes def decoder(bytearray): formatSize = { 'b': 1, 'B': 1, 'H': 2, 'h': 2, 'f': 4, 'I': 4, 'i': 4, } headers = ['acc_x','acc_y','acc_z','pitch','roll','humid','temp','light','light1','press','batt'] NR_VALS = 11 fin_i=0 curr_i = 0 decoded_val=[] for i in range(NR_VALS): fin_i = curr_i + formatSize[formats[i]] subPkt = bytes2send[curr_i:fin_i] decoded_val.append(struct.unpack(formats[i], subPkt)[0]) curr_i = fin_i return decoded_val ###################################################################################################################### ################################################ Ciclo principal ##################################################### while (True): pycom.rgbled(0x007f00) # green color comencing sequence bytes2send = bytearray() # bytearray que ira conter os valores em bytes a enviar values=[] formats = ['f','f','f','f','f','H','H','f','f','H','B'] #Total of 35 bytes + 13 bytes of LoRa header decoded_val=[] # a testar lora = LoRa(mode=LoRa.LORAWAN, region=LoRa.EU868) lora.nvram_restore() if not lora.has_joined(): print("Firstly join") dev_eui = ubinascii.unhexlify('70B3D54995F6E9F1') # these settings can be found from TTN app_eui = ubinascii.unhexlify('70B3D57ED0019C87') # these settings can be found from TTN 'o que estava aantes -- 70B3D57ED0019813' app_key = ubinascii.unhexlify('169C2EF739EAAF4051CD16B8CDA3D56A') # these settings can be found from TTN # set the 3 default channels to the same frequency (must be before sending the OTAA join request) lora.add_channel(0, frequency=config.LORA_FREQUENCY, dr_min=0, dr_max=5) lora.add_channel(1, frequency=config.LORA_FREQUENCY, dr_min=0, dr_max=5) lora.add_channel(2, frequency=config.LORA_FREQUENCY, dr_min=0, dr_max=5) # join a network using OTAA lora.join(activation=LoRa.OTAA, auth=(dev_eui, app_eui, app_key), timeout=0, dr=config.LORA_NODE_DR) # wait until the module has joined the network while not lora.has_joined(): time.sleep(2.5) pycom.rgbled(0x7f7f00) # yellow = lora.join pending print('Not joined yet...') print('LoRa joined!') pycom.rgbled(0x007f00) # green = lora.join complete # remove all the non-default channels for i in range(3, 16): lora.remove_channel(i) # 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, config.LORA_NODE_DR) # make the socket non-blocking s.setblocking(False) time.sleep(5.0) lora.nvram_save() print("AHHHHHHHHHHHHh") else: print("Join already") s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) s = socket.socket(socket.AF_LORA, socket.SOCK_RAW) s.setsockopt(socket.SOL_LORA, socket.SO_DR, config.LORA_NODE_DR) s.setblocking(False) # a testar #join_WLAN() #sync_RTC() values=readSensor() bytes2send=encoder(values, formats) print('bytes2send', bytes2send) #print('Array size:', len(bytes2send)) #decoded_val=decoder(bytes2send) #print("Decoded values: ", decoded_val) #print(len(decoded_val)) print("going to sleep") time.sleep(2) pycom.rgbled(0x0000ff) time.sleep(2) #mpp.i2c.writeto_mem(MPL3115A2.MPL3115_I2CADDR, MPL3115A2.MPL3115_CTRL_REG1, bytes([0x0])) s.send(bytes2send) lora.nvram_save() #time.sleep(10) py.setup_sleep(30) # setup a 10 seconds sleep time py.go_to_sleep(False) #machine.pin_deepsleep_wakeup(['P13'], machine.WAKEUP_ANY_HIGH, False) #time.sleep(2) #pycom.rgbled(0xff0000) #time.sleep(2) #machine.deepsleep(30000) # time.sleep(4) # rx, port = s.recvfrom(256) # if rx: # print('Received: {}, on port: {}'.format(rx, port)) # time.sleep(6) ##################### Debugging Section ##################### # a=base64.b64encode(bytes2send) # print(a) ############################################################# ######################################################################################################################```
-
@morrison my personal guess would be that you are going to sleep a bit too quickly after sending/saving state.
The Pysense-controlled Deep Sleep is quite brutal, it just cuts the power supply to the ESP32 without any warning.
Try adding short delays between send and save and between save and sleep to see if that helps.
Also, is your device rejoining each time, or just sending with the same counter over and over again?
-
@morrison Joining (via ABP or OTAA) just establishes the keys for data exchange between the nodes. These keys are established once and do not expire. If you like, you can renew the, but there is nothing enforcing it. And there is not session that expires.
Frame counter have to be managed at the node side. There is the lora.nvram_save / restore() mechanism, which is a little bit tricky, in that lora.nvram_restore() sets the stored counter to 0. So if you call it more than once in a row, you get 0 as counter value. That is, so to say, sub-optimal. If you request confirmed Lora messages, the message will be re-sent by the LoRa stack until confirmed, at least a few times. But that accumulates to the downlink budget, and some public networks limit that.
@CoachAllen These questions are partially pycom-specific and have been discussed several times in the forum.
-
@morrison What do you know? Another dead end from Pycom. You have a question and they ignore you. How does it feel to ALPHA a product?