Closed avillacis closed 1 year ago
I am not sure how this could be implemented, the internal parts of the LoRaMAC stack are taken from the Semtech code and I am not 100% familiar with it.
An option I see would be to use ABP instead of OTAA. With ABP you don't need to start the Join request/accept cycle every time. You just set the DevAddr, AppsKey and NWSKey and call join(). It will immediately return, as ABP doesn't require the join sequence.
Of course you have to setup the device in the LoRaWAN server as ABP device as well and use the same DevAddr, AppsKey and NWSKey.
avillacis, you are on the correct path here! Unfortunately, most current OTAA devices are not implemented correctly to spec... (rundown here https://lora-developers.semtech.com/documentation/tech-papers-and-guides/lorawan-device-activation/device-activation/ ). Ideally, OTAA devices would only have to do a join proper once per lifetime... Sadly, this doesn't seem to be the case pretty much anywhere, and full joins are used on each power cycle. (More info here https://lora-developers.semtech.com/documentation/tech-papers-and-guides/the-book/joining-and-rejoining/ )
So, if I understand correctly, for the OTAA case, the application should join the network successfully once, then retrieve the negotiated AppsKey and NWSKey somehow (is there an API for that?), and then, when waking up, retrieve and use the AppsKey and NWSKey in the ABP network join codepath, and it should work, right? Or am I forgetting something?
There should be an example program demonstrating the sequence, if the above strategy is possible and sound.
My proposal was to use ABP only, not start with OTAA and after wake-up use ABP.
I never tried it that way, but it could be working.
SUCCESS!
I could successfully recover enough state from the OTAA negotiation using existing APIs, to persist the session across a full device reset and keep sending packets using the exact same keys. The procedure done is as follows:
MIB_DEV_ADDR
, MIB_NWK_SKEY
, MIB_APP_SKEY
. All of these are retrieved through the LoRaMacMibGetRequestConfirm()
function.MIB_UPLINK_COUNTER
and MIB_DOWNLINK_COUNTER
with the same function as before.lmh_setNwkSKey
, lmh_setAppSKey
, lmh_setDevAddr
and then lmh_init
should be called in ABP mode, with OTAA flag set to FALSE.LoRaMacMibSetRequestConfirm()
function and the MIB_UPLINK_COUNTER
and MIB_DOWNLINK_COUNTER
specifiers. This keeps the network from rejecting the packets with a frame counter reset error.Glad you found a solution. Thank you for sharing it here. I mark this with a best practice label for others.
@avillacis this is just what I've been searching for. Would you mind sharing your example?
@avillacis thanks for sharing this!
Just to be clear, you do not have to ever tell the LNS that you are conducting ABP effectively, correct? You're just using that mode device side because you have the session keys stored?
@avillacis this is just what I've been searching for. Would you mind sharing your example?
Sorry for answering so late, but I was (and still am) very busy with my day job. The procedure I shared previously is a distillation of an algorithm I implemented in a framework I am responsible for. The procedure is not (yet) demonstrated in a standalone example, but I implemented it in this commit and was refined in the following commits for the yubox-LoRaWAN addon library for the YUBOX-Now framework (NOTE: assumes ESP32 or ESP32-S2 environment).
@avillacis thanks for sharing this!
Just to be clear, you do not have to ever tell the LNS that you are conducting ABP effectively, correct? You're just using that mode device side because you have the session keys stored?
That is right. The Chirpstack instance has the device registered as requiring OTAA, but it does not know nor care that the device was rebooted between transmissions, as long as packets keep being sent with the proper negotiated keys. As mentioned when opening this issue, the purpose was to skip renegotiation via OTAA after waking from ESP32 deep sleep, which is almost equivalent to a reboot.
Hello. We are using your library successfully for several of our IoT projects that need communication in areas without WiFi coverage. However we have the following issue. At least one of our projects needs to run off a combination of solar panels and batteries in order to transmit 24/7 without mains power. So, obviously we make use of deep-sleep. However, every time the device (an ESP32-S2) comes out of deep sleep, it needs to negotiate the join to the LoRaWAN network all over again, which takes time it could be using instead sending its sample backlog.
Is there a way to extract some summary or current state of the LoRaWAN authentication state (assuming the device joined the network successfully), so it can be saved to flash or RTC memory, and be restored on wakeup? This would greatly accelerate data transmission.