# OTAA best practice: how to not join every time?

**URL:** <https://www.thethingsnetwork.org/forum/t/otaa-best-practice-how-to-not-join-every-time/14601>\
**Category:** End Devices (Nodes)\
**Created:** [May 28, 2018, 2:53pm UTC](https://www.thethingsnetwork.org/forum/t/otaa-best-practice-how-to-not-join-every-time/14601 "2018-05-28T14:53:28Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![teluu](https://www.thethingsnetwork.org/forum/user_avatar/www.thethingsnetwork.org/teluu/32/14073_2.png) [@teluu](https://www.thethingsnetwork.org/forum/u/teluu)\
**Post date:** [May 28, 2018, 2:53pm UTC](https://www.thethingsnetwork.org/forum/t/otaa-best-practice-how-to-not-join-every-time/14601/1 "2018-05-28T14:53:28Z")

</div>

In [https://www.thethingsnetwork.org/docs/devices/bestpractices.html](https://www.thethingsnetwork.org/docs/devices/bestpractices.html)

nodes should only join minimally.

However in all examples:

> **[TheThingsNetwork/arduino-device-lib](https://github.com/TheThingsNetwork/arduino-device-lib/tree/master/examples)**
>
> Arduino Library for TTN Devices. Contribute to TheThingsNetwork/arduino-device-lib development by creating an account on GitHub.

every time a device powered up it does a join. Does this violates best practice?

---

<div class="post-metadata">

**Author:** ![BoRRoZ](https://www.thethingsnetwork.org/forum/user_avatar/www.thethingsnetwork.org/borroz/32/44234_2.png) [@BoRRoZ](https://www.thethingsnetwork.org/forum/u/BoRRoZ)\
**Post date:** [May 28, 2018, 3:39pm UTC](https://www.thethingsnetwork.org/forum/t/otaa-best-practice-how-to-not-join-every-time/14601/2 "2018-05-28T15:39:25Z")

</div>

> [@teluu](#):
>
> every time a device powered up it does a join. Does this violates best practice?

that happends when under development… not IRL 😉

a possible solution

1e time OTAA join + set counter to 1  
store keys

2e time ABP join (read keys from memory) + counter +1  
3e time same  
.  
.  
xx time start all over OTAA join (+ store new keys) + counter start at 0

---

<div class="post-metadata">

**Author:** ![teluu](https://www.thethingsnetwork.org/forum/user_avatar/www.thethingsnetwork.org/teluu/32/14073_2.png) [@teluu](https://www.thethingsnetwork.org/forum/u/teluu)\
**Post date:** [May 28, 2018, 3:54pm UTC](https://www.thethingsnetwork.org/forum/t/otaa-best-practice-how-to-not-join-every-time/14601/3 "2018-05-28T15:54:37Z")

</div>

OK, so how do I get the device address after OTAA? I can’t see any methods on the SDK.

---

<div class="post-metadata">

**Author:** ![Edzelf](https://www.thethingsnetwork.org/forum/user_avatar/www.thethingsnetwork.org/edzelf/32/46364_2.png) [@Edzelf](https://www.thethingsnetwork.org/forum/u/Edzelf)\
**Post date:** [May 29, 2018, 12:28pm UTC](https://www.thethingsnetwork.org/forum/t/otaa-best-practice-how-to-not-join-every-time/14601/4 "2018-05-29T12:28:27Z")

</div>

See [here](https://github.com/Edzelf/LoRa/tree/master/ESP_lora_tracker) an example for the ESP8266. OTA is used just once. The keys and the counter are saved in RTC memory (retrieved from here if power is still on at wake-up) and in EEPROM (retrieved from here if completely powered off).

---

<div class="post-metadata">

**Author:** ![teluu](https://www.thethingsnetwork.org/forum/user_avatar/www.thethingsnetwork.org/teluu/32/14073_2.png) [@teluu](https://www.thethingsnetwork.org/forum/u/teluu)\
**Post date:** [May 30, 2018, 2:17pm UTC](https://www.thethingsnetwork.org/forum/t/otaa-best-practice-how-to-not-join-every-time/14601/5 "2018-05-30T14:17:55Z")

</div>

Thanks @Edzelf though I can see this is using LMIC. I’m currently using Sodaq Explorer with RN2483 - I can’t yet see a way to retrieve the device address that is assigned after OTAA joining.

---

<div class="post-metadata">

**Author:** ![Edzelf](https://www.thethingsnetwork.org/forum/user_avatar/www.thethingsnetwork.org/edzelf/32/46364_2.png) [@Edzelf](https://www.thethingsnetwork.org/forum/u/Edzelf)\
**Post date:** [May 30, 2018, 3:00pm UTC](https://www.thethingsnetwork.org/forum/t/otaa-best-practice-how-to-not-join-every-time/14601/6 "2018-05-30T15:00:08Z")

</div>

Saving and retrieving the data has nothing to do with LMIC. You just need a way to store data in a non-volatile memory of your device. I’m not familiar with Sodaq, so I can’t help you with it.

---

<div class="post-metadata">

**Author:** ![kersing](https://www.thethingsnetwork.org/forum/user_avatar/www.thethingsnetwork.org/kersing/32/44777_2.png) [@kersing](https://www.thethingsnetwork.org/forum/u/kersing)\
**Post date:** [May 30, 2018, 3:04pm UTC](https://www.thethingsnetwork.org/forum/t/otaa-best-practice-how-to-not-join-every-time/14601/7 "2018-05-30T15:04:33Z")

</div>

From the RN2483 manual:

> 2.4.9.1 mac get devaddr  
> Response: 4-byte hexadecimal number representing the device address, from  
> 00000000 to FFFFFFFF.  
> This command will return the current end-device address of the module. Default: 00000000

If your library does not provide this you will need to add it (or find a library that supports these commands)

---

<div class="post-metadata">

**Author:** ![teluu](https://www.thethingsnetwork.org/forum/user_avatar/www.thethingsnetwork.org/teluu/32/14073_2.png) [@teluu](https://www.thethingsnetwork.org/forum/u/teluu)\
**Post date:** [May 31, 2018, 12:45pm UTC](https://www.thethingsnetwork.org/forum/t/otaa-best-practice-how-to-not-join-every-time/14601/8 "2018-05-31T12:45:36Z")

</div>

It is confirmed that the current SODAQ library [does not support it](http://forum.sodaq.com/t/how-do-retrieve-device-address/1659/2?u=ismangil).

---

<div class="post-metadata">

**Author:** ![brulath](https://www.thethingsnetwork.org/forum/user_avatar/www.thethingsnetwork.org/brulath/32/35697_2.png) [@brulath](https://www.thethingsnetwork.org/forum/u/brulath)\
**Post date:** [June 2, 2018, 10:44am UTC](https://www.thethingsnetwork.org/forum/t/otaa-best-practice-how-to-not-join-every-time/14601/9 "2018-06-02T10:44:17Z")

</div>

As a note on this, if your device shuts down RAM during its sleep mode then you’ll want to make sure you’re saving everything; performing an ABP join is not sufficient to restore a LoRaWAN client state properly. It may work on TTN, for now, but it’s not likely to work anywhere else (and may not be sufficient in the future for TTN).

As an example, there’s a MAC command to request the battery level and RSSI (gateway to node) from the node. If you receive that command you have to either respond immediately or keep track of the request for the next time you transmit. Other MAC commands can change the channels available, RX frequency on a per-channel basis, RX windows, max EIRP, mask out channels, etc. Not tracking these may result in communication loss.

Adaptive Data Rate (ADR) information is lost if you don’t keep track of it. If the server instructs your device to use DR4, but you power-cycle, set ABP, then transmit, your node won’t remember the data rate to use.

Some things to monitor:

- Uplink and downlink counters must be tracked
- Network and app session keys, device ID, etc. must be tracked
- Adaptive data rate state including target data rate, ADR ack counter, etc. must be tracked
- Joins can provide channel plans which must be tracked
- MAC commands which change settings/channels/frequencies/rx frequencies/max EIRP/etc. must be tracked
- MAC commands which require a response (i.e. request battery level/RSSI) must either be serviced immediately or tracked
- _(there’s more I can’t recall off-hand)_

---

<div class="post-metadata">

**Author:** ![BoRRoZ](https://www.thethingsnetwork.org/forum/user_avatar/www.thethingsnetwork.org/borroz/32/44234_2.png) [@BoRRoZ](https://www.thethingsnetwork.org/forum/u/BoRRoZ)\
**Post date:** [June 2, 2018, 11:00am UTC](https://www.thethingsnetwork.org/forum/t/otaa-best-practice-how-to-not-join-every-time/14601/10 "2018-06-02T11:00:14Z")

</div>

> [@brulath](#):
>
> MAC commands which require a response (i.e. request battery level/RSSI) must either be serviced immediately or tracked

why ? what happends if the node don’t respond immediate because it went to sleep that moment, and now wakes up again after one hour ?  
_I can imagine that the node, before going into deepsleep, first must ‘finish’ his business_

for example the RN2483A

![mac%20save](https://www.thethingsnetwork.org/forum/uploads/default/original/2X/2/2108e06618ce14e53a83747d34848ea060ae79cb.jpg)

---

<div class="post-metadata">

**Author:** ![arjanvanb](https://www.thethingsnetwork.org/forum/user_avatar/www.thethingsnetwork.org/arjanvanb/32/46626_2.png) [@arjanvanb](https://www.thethingsnetwork.org/forum/u/arjanvanb)\
**Post date:** [June 2, 2018, 11:35am UTC](https://www.thethingsnetwork.org/forum/t/otaa-best-practice-how-to-not-join-every-time/14601/11 "2018-06-02T11:35:45Z")

</div>

I don’t think a node ever needs to reply immediately. But indeed, like for a confirmed downlink, it needs to store the fact that a confirmation was requested, so it can set the ACK bit in the next uplink. Even if that uplink is days later. When not doing that, then TTN will be required to send the downlink again.

(So I guess `mac save` indeed does not suffice there. ~~But I even don’t see the frame counters mentioned above, so maybe `mac save` is just not the right command at all, or~~ though the documentation is outdated, see below.)

Related:

- [OTAA then ABP](https://www.thethingsnetwork.org/forum/t/otaa-then-abp/12377)
- [How often should a node do an OTAA Join, and is OTAA better than ABP?](https://www.thethingsnetwork.org/forum/t/how-often-should-a-node-do-an-otaa-join-and-is-otaa-better-than-abp/11192)

---

<div class="post-metadata">

**Author:** ![brulath](https://www.thethingsnetwork.org/forum/user_avatar/www.thethingsnetwork.org/brulath/32/35697_2.png) [@brulath](https://www.thethingsnetwork.org/forum/u/brulath)\
**Post date:** [June 2, 2018, 11:45am UTC](https://www.thethingsnetwork.org/forum/t/otaa-best-practice-how-to-not-join-every-time/14601/12 "2018-06-02T11:45:16Z")

</div>

> why ? what happends if the node don’t respond immediate because it went to sleep that moment, and now wakes up again after one hour ?

That’s what I meant by “tracked”, as in you have to keep track of the request and service it during your next transmission. If you aren’t keeping track of it then you should probably send another transmission immediately before you go to sleep which does service it, as the request would be lost otherwise.

---

<div class="post-metadata">

**Author:** ![BoRRoZ](https://www.thethingsnetwork.org/forum/user_avatar/www.thethingsnetwork.org/borroz/32/44234_2.png) [@BoRRoZ](https://www.thethingsnetwork.org/forum/u/BoRRoZ)\
**Post date:** [June 2, 2018, 11:48am UTC](https://www.thethingsnetwork.org/forum/t/otaa-best-practice-how-to-not-join-every-time/14601/13 "2018-06-02T11:48:06Z")

</div>

or maybe even answer before going into sleep ? if that’s possible …

---

<div class="post-metadata">

**Author:** ![arjanvanb](https://www.thethingsnetwork.org/forum/user_avatar/www.thethingsnetwork.org/arjanvanb/32/46626_2.png) [@arjanvanb](https://www.thethingsnetwork.org/forum/u/arjanvanb)\
**Post date:** [June 2, 2018, 12:07pm UTC](https://www.thethingsnetwork.org/forum/t/otaa-best-practice-how-to-not-join-every-time/14601/14 "2018-06-02T12:07:54Z")

</div>

> [@brulath](#):
>
> Some things to monitor:
> 
> - Uplink and downlink counters must be tracked
> - Network and app session keys, device ID, etc. must be tracked
> - Adaptive data rate state including target data rate, ADR ack counter, etc. must be tracked
> - Joins can provide channel plans which must be tracked
> - MAC commands which change settings/channels/frequencies/rx frequencies/max EIRP/etc. must be tracked
> - MAC commands which require a response (i.e. request battery level/RSSI) must either be serviced immediately or tracked
> - _(there’s more I can’t recall off-hand)_

And:

- Channel usage for proper channel hopping.
- Channel usage for regional duty cycle limitations.
- Very much part of your second-last bullet, but just to make it explicit for future readers: pending confirmations for confirmed downlinks.
- For LoRaWAN 1.0.x: maybe all used values for the OTAA DevNonce; see [OTAA shows "Activation DevNonce not valid: already used"](https://www.thethingsnetwork.org/forum/t/otaa-shows-activation-devnonce-not-valid-already-used/5079).
- For LoRaWAN 1.1x: [the OTAA join counter (nonce)](https://www.thethingsnetwork.org/forum/t/otaa-shows-activation-devnonce-not-valid-already-used/5079/18).

As an aside, [since version 1.0.0](https://www.thethingsnetwork.org/forum/t/first-lorawan-certification-program-pass/875/2) the RN2483 `mac save` command [saves much more](http://ww1.microchip.com/downloads/en/DeviceDoc/40001784C.pdf#page=23), and _does_ include the frame counters, but no mention of the pending MAC command responses. (But maybe more recent versions even include that?)

See also [How to persist LMIC OTAA parameters with an ESP32?](https://www.thethingsnetwork.org/forum/t/how-to-persist-otaa-paramenters-with-an-esp32/35032)

---

<div class="post-metadata">

**Author:** ![teluu](https://www.thethingsnetwork.org/forum/user_avatar/www.thethingsnetwork.org/teluu/32/14073_2.png) [@teluu](https://www.thethingsnetwork.org/forum/u/teluu)\
**Post date:** [June 2, 2018, 12:37pm UTC](https://www.thethingsnetwork.org/forum/t/otaa-best-practice-how-to-not-join-every-time/14601/15 "2018-06-02T12:37:38Z")

</div>

I propose there is also a best practice example, after the quickstart, using TTN libraries at least on how to do all the above.

---

<div class="post-metadata">

**Author:** ![de-elmshorn-1](https://www.thethingsnetwork.org/forum/user_avatar/www.thethingsnetwork.org/de-elmshorn-1/32/39868_2.png) [@de-elmshorn-1](https://www.thethingsnetwork.org/forum/u/de-elmshorn-1)\
**Post date:** [July 28, 2019, 3:03pm UTC](https://www.thethingsnetwork.org/forum/t/otaa-best-practice-how-to-not-join-every-time/14601/16 "2019-07-28T15:03:02Z")

</div>

Issuing a “sys factoryRESET” may help to get an ‘accepted’ reply from RN2483A module. If you use “mac save” be sure to have valid data for devaddr, appeui and appkey. This project may help too: [https://github.com/thomaswesenberg/LoRaWAN-device-GPS-RaspBerry-Pi](https://github.com/thomaswesenberg/LoRaWAN-device-GPS-RaspBerry-Pi)
