Node adoption for The Things Stack V3

I was quite surprised and and a little bit shocked by this message on the Things Stack (V2) Console:

What does it mean?, how do I get my running LoRa nodes to the V3 Stack? How much work must be done? Can I still use all my nodes?

My nodes still working on V3?

In the past years I developed two main nodes: One based on a RFM95W module and ATtiny84 controller (8k flash) and one based on a RFM95W module and a STM32L051 controller (64k flash) called the MiniPill LoRa. I was not afraid this one could handle the Things Stack V3. I have enough memory to run OTAA and latest LMIC library, although some use the proprietary library to get more flash for the sensor-code they use. The main problem was the ATtiny84 with proprietary library for the LoRaWAN communication. It can handle only ABP and cannot receive downlink messages. In most situations you do not need them. You only want to have upload the data from your sensor periodically and use as minimal power as possible.

The testing phase

I have build a V3 gateway and got it up and running (see previous blog) and hence had a test environment for my nodes. I have a few MiniPill LoRa nodes with the proprietary library for testing and of course the LMIC1.5 (used) and the new LMIC1.6 library. Most code is Arduino based, and sometimes proprietary for the STM32 or ATtiny84 controller. The first test show a good result.

Problem description

The main problems of ABP nodes that cannot receive and react on downlink messages is that the Stings Stack V3 keeps on sending downlink messages until the node responds. The Things Stack assumes every node will comply to the the LoRaWan specification. There are two situations the Things Stack will send messages to the node:

  • After the first received packet the send the MAC command RXParamSetupReq (0x08), this one must be answered with a RXParamSetupAns. On the Stack V3 the policy is to set the RX1 delay to 5 seconds instead of the default 1 second.
  • After a period of time or frame count the Things Stack will send the MAC command DevStatusReq (0x06), this one must be answered with a DevStatusAns. I have figured out that these messages are usualy send at 201, 402, 603, etc. It seems to me the calclation is 200 + downlink frame counter.

When you do not answer these request the downlink messages will continue. This is not a nice situation. With several nodes you get a lot of messages send by your gateway in the air. I do wonder why there is not a maximum of downlink request set on this, but that is another discussion. I also wonder why they send DevStatusReq packets by default, me and my node do not want to give this information to the Stack.

Warning before using this solution

Use this solution and code examples on your own risk. I do encourage you to use a node with the latest LMIC library that is compliant with the LoRaWAN specification. However I really can imagine that the time, money and effort you put in your existing nodes you do not want to throw away. I hope to help you with this article to move your existing nodes to the Things Stack V3. The Things network is build upon the efforts, money and time spend by many people with technical interest and I hope this will continue with support for legacy (V2) nodes.
Be aware that some people on the The Things Stack will be upset by this hacked solution. When you can please use the LMIC code for the MiniPill LoRa Node, see links to that code on other blog-articles.


The solution is basically based on two things:

  1. Answer the RXParamSetupReq (0x08) after sending the first frame as if you could receive the downlink package.
  2. Disable the DevStatusReq (0x06) for the node that cannot or you do not want to receive Device Status Requests.

The first point was easy to accomplish. Just send a well formed RXParamSetupReq send on the second frame. This means a little addition of code to the proprietary library.
The Things stack fortunately gave a hint to the solution for the second point:

To set the StatusTimePeriodicity and StatusCountPeriodicity to 0 you have to use the CLI (Command Line Interface) from the Things Stack V3.

In the next paragraphs I will describe how to create a new ABP node on the The Things Stack V3 and make the modification so you can use it as it was connected to the Things Stack V2.

First Step: create a new node on the things Stack

Create an Application and then add a new node on The Things Stack V3

ABP settings on The Things Stack V3

  • Add a new End Device in V3 (Manual)
  • Select Activation by Personalization (ABP)
  • The LoRaWAN version is probably v1.0.2
  • In the Basic settings step:
  • The DevEUI is optional
  • In Network layer settings step:
  • Select a Frequency Plan. For EU868 devices coming from V2, you select Europe 863-870 MHz (SF9 for RX2 – recommended)
  • Regional Parameter version is probably v1.0.2 rev B
  • Your device does not support class B or class C
  • in Advances settings options at Network layer settings:
    (must be set on registration, changing these later may not work)
    • The Frame counter width is probably 32 bit
    • The RX1 Delay is 5 seconds
    • The RX1 Data Rate Offset is 0
    • Optional Resets Frame Counters Enabled
      this options disable dropping messages after reseting the frame counter. This was not working until Things Stack v3.12.
    • The RX2 Data Rate Index for EU868 devices is 3
    • The RX2 Frequency for EU868 devices is 869525000
    • The Factory Preset Frequencies for EU868 devices with 8 channels is:
      • 868100000, 868300000, 868500000
      • 867100000, 867300000, 867500000, 867700000, 867900000

This setup can also be done with the CLI bus is not described here.

Second Step: set StatusTimePeriodicity and StatusCountPeriodicity to 0

Use the ttn-lw-cli and login to the Things Stack. Read the paragraph at the end of this blog for information how to connect with the CLI to the Community version of the Stack V3.

Get a list of applications

ttn-lw-cli applications list

Get a list of devices for application

ttn-lw-cli end-devices list <your application-id>

Set and get status-count-periodicity to 0

ttn-lw-cli end-devices set <your application-id> <your device-id> --mac-settings.status-count-periodicity 0

ttn-lw-cli end-devices get <your application-id> <your device-id> --mac-settings.status-count-periodicity 0

Set and get status-time-periodicity to 0 seconds

ttn-lw-cli end-devices set <your application-id> <your device-id> --mac-settings.status-time-periodicity 0

ttn-lw-cli end-devices get <your application-id> <your device-id> --mac-settings.status-time-periodicity 0

Get and reset frame counters

Sometimes you have to reset the counters after a reboot of your device or when you are testing. Otherwise the frames will be rejected due to difference of counters.

ttn-lw-cli end-devices get <your application-id> <your device-id> --session.last-f-cnt-up

ttn-lw-cli end-devices reset <your application-id> <your device-id> --session.last-f-cnt-up

ttn-lw-cli end-devices get <your application-id> <your device-id> --session.last-a-f-cnt-down

ttn-lw-cli end-devices reset <your application-id> <your device-id> --session.last-a-f-cnt-down

Third Step: Use the code with the proprietary library

Use the code with the proprietary library and use the #define TTNSTACKV3 setting at the start of the main.cpp file. In that case the second frame send after reboot will send a confirming RXParamSetupAns. See the code in LoRaWAN.cpp file.

Links to updated code with proprietary libraries for the ATtiny node and MiniPill LoRa Node:

The code is not yet extensive tested. First test are running and looking good.

CLI on Community The Things Stack V3

To get the CLI working you should take a few steps:

  1. Install the ttn-lw-cli on your operating system. This is described here:
  2. Create a Personal API key. This is the an easy way to setup a trust between your PC and the Stack:
    1. Login to the Console of the Things Stack V3
    2. Click on the right top corner on your login name
    3. Select Personal API keys
    4. Click on Add API Key
    5. Add a key and copy the one-time-showing generated key. This is the key (quite long) you should use in one of the next steps
  3. run the command to setup the configuration: ttn-lw-cli use
    In the documentation of The Things Stack V3 the server name <tenant-id> is used.
  4. login to the Stack: ttn-lw-cli login --api-key <key derived from previous step>
  5. Now you can run the commands to set StatusTimePeriodicity etc.

Technical background on RXParamSetupAns

The Things stack will send and frame with the next FOpts MAC commands:

05 03 d2 ad 84 06

05 = RXParamSetupReq

03 d2 ad 84 = Parameters of the RXParamSetupReq with RX1 timing and channels used

06 = DevStatusReq

In the code I only respond to the 05 RXParamSetupReq with a 05 (RXParamSetupAns) command and 07 parameter (all parameters successful set). I do ignore the 06 DevStatusReq. In my experiments the downlink messages stopped after answering with RXParamSetupAns.

One thought on “Node adoption for The Things Stack V3

Leave a Reply

Your email address will not be published. Required fields are marked *